In this script we estimate residual pool characteristics. The residual pool is the pool that would form if streamflow were to decrease to zero. Its depth is characterised as the elevation difference between the pool’s deepest point and the pool outlet / riffle crest that controls the flow of water out of the pool. It serves as a flow-independent metric of pools in a stream and, with several assumptions, we can estimate the depths, areas, and volumes of residual pools based on our field data. See Lisle (1989) for more background on the concept of residual depths.

We tried to make field data collection as simple as possible by relying on water depths rather than elevations for our longitudinal profiles, so that people could collect data without survey equipment - reducing the cost and expertise required, and facilitating assessment in densely vegetated / woody coastal streams, highly incised channels etc. The use of simple depth data requires a couple of extra processing steps compared with using elevation data, but luckily some rather clever individuals have already figured it out.

The code we use here is adapted from the ‘Rapid Bed Profile’ approach from Stack (1989), with additional guidance from Kaufman et al. (1999), and we adopt Stack’s slope factor. The slope factor was developed in coastal streams but has been applied successfully in a variety of other systems. If you have the resources, the accuracy of the slope factor for your particular system can be tested by comparing water-depth-derived to elevation-derived residual pool data. However, even if this assumption is untested (as it will be in most cases), the resulting metrics remain valid for assessing changes within a system, as long as you don’t change the slope factor between years or reaches in your comparison.

Data import

First we will import the tidied dataframe generated by the Data Wrangling script, which was exported to your output folder. This file has longitudinal thalweg water depth data that includes both regular predetermined spacing and any ‘extra’ pool outlets and max pool depths encountered (‘XPO’, ‘XD’). We proposed that the ‘extra’ measurements were taken in the field, in order to capture the depth minima (potential pool outlets) and maxima (deepest pool sections) that might occur between regular intervals.

In this code we will require some additional constants that we ask you to define in the code below based on data you recorded in the field (or are able to estimate). This is done by creating a dataframe/table, for which you must enter the following:

Enter this information in the code below. Data is entered in vectors of equal length and following the same sequence. For example, in the existing code, Hatchery Channel is associated with spacing of 1 and 1, slope of 1 and 1.1, and wetted width of 6.8 and 7.0, for 2024 and 2025 respectively. Once you create the dataframe with your data, check through the table to ensure these constants are assigned to the correct reach & year.

# Create a data frame to hold constants for multiple sites and years. Enter your data below:
constants_df <- data.frame(
  Site = c("Hatchery Channel", "Hatchery Channel", "Brousseau Channel", "Brousseau Channel"),  # Edit / Add your site names
  year = c(2024, 2025, 2024, 2025),  # Corresponding years for each site
  spacing = c(1, 1, 1, 1),  # spacing values for each site-year combination
  Slope = c(0.5, 0.6, 0.5, 0.5),    # Slope values for each site-year combination, in %
  WetWidth = c(6.8, 7.0, 6.5, 7.1)  # Average wetted width in m, for each site-year combination
)

# View the constants data frame
print(constants_df)
##                Site year spacing Slope WetWidth
## 1  Hatchery Channel 2024       1   0.5      6.8
## 2  Hatchery Channel 2025       1   0.6      7.0
## 3 Brousseau Channel 2024       1   0.5      6.5
## 4 Brousseau Channel 2025       1   0.5      7.1

Creation of Residual Surfaces

The residual surface is the water surface at the point when streamflow approaches zero, and residual depth is the vertical distance between the residual surface and the stream bed. As such, when we estimate residual pools and residual depths, these are features that are independent of flow conditions at the time of the field survey. While they might be representative of actual pool conditions during times of very low flow, their value lies with the ability to make comparisons of pool habitat among years and/or reaches without quantifying and controlling for variable flow conditions.

Our code uses the sequence of thalweg depth measurements to identify potential pool outlets in the sampled reach, and estimates residual depths at each measurement location based on a projected residual surface that extends upstream from each pool outlet. The residual surface is projected using the expected pool water surface slope (which is estimated using Stack’s empirical equation, incorporating the average reach slope that you entered as a constant).

It is important to note that when we identify pool outlets or riffle crests (either in the field or using this code), we usually base this determination on the bed elevation and/or water depth at the current location compared with the areas immediately adjacent. However, a potential pool outlet will not ‘behave’ as a pool outlet under all flow conditions: it could be high and dry under very low flow conditions, or it could itself be within a pool due to the backwatering effects of a higher-elevation pool outlet downstream. From here onward, we will use the term ‘local depth minima’ (‘LDM’ in code) to refer to locations that have the potential to be pool outlets - that is, they are less deep than areas immediately downstream and upstream, accounting for the slope of the stream. We will reserve the term ‘pool outlet’ for cases when local depth minima would be expected to actually backwater a pool under flow conditions approaching zero.

At this point our code will generate a new dataframe (residuals.df) with the local depth minima identified and the residual surface projected. If you are interested in how this is done, check out the R code. For everyone else, here are some fish:

🐟🐟🐟🐟🐟 🐟🐟🐟🐟🐟 🐟🐟🐟🐟🐟 🐟🐟🐟🐟🐟 🐟🐟🐟🐟🐟 🐟🐟🐟🐟🐟 🐟🐟🐟🐟🐟 🐟🐟🐟🐟🐟 🐟🐟🐟🐟🐟

Below we generate a quick visual of the depths and residual surfaces that were projected by the code. Take a look to ensure it matches your understanding of residual pools and look for potential errors (the figure is interactive, so zoom in if you have several plots). Try to identify some local depth minima that are within a pool (if present in your data), and compare these to the local depth minima that act as pool outlets - the shallower features at which residual surfaces begin. Remember that the residual surface slopes down in these figures as you progress upstream (right in the plots), which is to compensate for the fact that the true thalweg surface slopes down as you progress downstream.

‘Meaningful’ Pools

Consider the vertical exaggeration of the above figure - some ‘pools’ may be very shallow indeed, and might not necessarily correspond with what you would actually consider a pool in a stream.

It is probably most informative to consider metrics relating only to those pools that are expected to be hydraulically and/or biologically meaningful. The code now detects pools and assigns each a pool ID, so that we can characterise them individually and select subsets as appropriate.

The above figure should show a series of distinct pools and is exported to your output folder. Don’t worry if the shading cuts off before the pool’s upstream extent, this is just an artefact associated with my limited figure-plotting abilities. The important thing to note is that the calculations below will integrate the full area beneath the residual surface for each pool.

Pool Metrics

The code now calculates the following metrics for each residual pool:

  • Maximum depth;

  • Pool length (pool outlet to where the residual surface meets the thalweg at the upstream end of the pool); and

  • Sagittal area.

Sagittal refers to a plane that divides a body into left and right, so imagine a two-dimensional vertical screen extending downstream all along the thalweg, separating river left from river right. Within each residual pool, the sagittal area corresponds to the surface area of that screen. Too abstract? Take a look at the above figure again: Each of the shaded areas corresponds to the sagittal area for that particular residual pool - sagittal area integrates each depth measurement over the length of the pool. Although this may not be as intuitive as pool volume, it requires fewer assumptions than will be necessary to generate estimates of pool volume (i.e., regarding cross-sectional channel shape of pools at zero flow, wetted widths). Because fewer assumptions are required, and because it easily corresponds to 2D visualisations like the one above, we recommend using sagittal area rather than volume for a metric tracking changes in pool habitat (though we will also calculate volume later).

Subsetting Pools

So far we have identified all of the residual pools, but depending on your dataset some of the pools visualised above might look more like puddles. So to focus our summary statistics on pools that better align with what we consider biologically- and/or geomorphically-meaningful, we can use the metrics we just calculated to focus on a specific subset of deeper pools.

In terms of subsetting pools, some people use a specific depth cut-off for a species of interest (e.g., Mossop and Bradford 2006 used 0.1 m). Alternatively the pools that we focus on can be based on physical characteristics of the sampled reach. We will do the latter, keeping this code more widely applicable, by following Stack (1989) who determined meaningful pools as those that had a maximum depth greater than or equal to the standard deviation of depth for the reach.

In the following code chunk it reads ‘custom_depth <- NULL’. This is our default subsetting (selects only pools with a maximum residual depth greater than the standard deviation of the residual depths for the entire sampled reach). If you want to subset the pools in another way, you can modify the code here. For example, if it is biologically meaningful for your system to consider only pools that are 0.1 m deep or greater during approaching-zero-flow periods, you can specify ‘custom_depth <- 0.1’. Or, if you want to consider all pools no matter how shallow, then assign custom_depth a value of ‘0’. Just be sure to compare like-for-like when you consider different years/sites that you may wish to compare.

# Add a custom depth threshold in metres, or leave as 'NULL' to use standard deviation. If you are interested in all of the residual depths (i.e., not subsetting), just enter '0' for the custom_depth
custom_depth <- NULL

The table above has been exported to your output folder. It displays the subset selection of residual pools, the sagittal area of each pool, the maximum residual depth (deepest point per pool at zero flow), and the pool length of each pool. When considered at the reach-scale, summary statistics of the maximum residual depth and pool length have been considered useful metrics to track pool quality and quantity (e.g., Lisle 1986, Mossop and Bradford 2006, Clark et al 2019).

The reach mean of the pool maximum residual depths has been used as a proxy for pool quality, and positive relationships with Chinook salmon density have been demonstrated (e.g., Mossop and Bradford 2006). Relationships between habitat metrics and biota can be highly context-dependent, and independent verification is recommended where possible. However, as the resources required to test these assumptions are often prohibitive, we recommend taking advantage of relationships that have already been quantitatively demonstrated in the scientific literature. Although it is possible to generate quantitative estimates of biotic densities if the relationship between habitat metric and biotic density is monotonic, we feel that this is too speculative without data for your individual system. However, for the purpose of restoration monitoring, we feel it is incredibly powerful to be able to demonstrate (e.g.) that we have caused an x-sized increase in a habitat metric that is known to be positively correlated with target species density in a similar system.

The proportional length of pools in the reach also has demonstrated positive relationships with coho, Chinook densities (Clark et al 2019). Bear in mind that there will always be nuance involved in the application and interpretation of habitat metrics. You must understand and predict, in an a priori fashion, what your restoration objectives are with respect to habitat: Does your reach need more pool of a certain depth? Is your reach lacking much-needed riffles? Presumably there are cases where the reach has too much pool habitat. These types of questions are best addressed with well-matched reference sites, but local knowledge and the scientific literature will also be of great help.

We will now generate and export to your output folder some summary statistics, including the aforementioned mean max residual depth and length in residual pool, for your data:

These above statistics should be useful for tracking changes over time, or comparing reference / control reaches. Because they are all based on residual depths, they are flow-independent.

Total sagittal area and proportion of the reach length in residual pool should be compared between years and/or sites, and you can interpret whether the changes are in the predicted direction and of a meaningful magnitude. Since these two metrics have one value per reach, the metrics themselves cannot be evaluated statistically (unless you have a large number of reaches/years), however a directional change over time that aligns with your predictions is obviously quite a good sign.

Inferential Tests

We can apply inferential statistical tests to the sagittal area, maximum pool depth, and pool length data - that is, the data which have values at the level of each pool (i.e., a population of values is available per reach/year). We will use inferential statistical tests to determine whether the differences we observed among reaches and years are likely to be due to chance. You will be familiar with p values of 0.05 (observed result expected just due to chance 1 in 20 times) and we will use p=0.05 as our cut-off here. However, depending on your adaptive management plans, you may be willing to accept different levels of certainty, and p values of 0.1 are not unheard of in restoration projects. This all depends on the risk tolerance of you and your team, and should be established before conducting analyses.

For these inferential tests we will use ANOVAs because of their familiarity for ecologists and expected suitability for the data. For the metrics relating to residual pools that we have generated, we will test for differences between sites, years, and an interaction of sites*years (i.e., did the different locations change differently over time). The code uses the subset of pools that were defined earlier as ‘meaningful’.

Choice of Metric: At this point, you should choose which of ‘sagittal area’, ‘maximum pool depth’, and ‘pool length’ best aligns with your needs (e.g., relevance to restoration objective, comparisons with literature, ease of communication). You will base your interpretation of the ANOVA on this chosen metric, even though we will run ANOVA for all three.

The reason for selecting one metric for interpreting your hypothesis is that the metrics are not independent of one another: Sagittal area incorporates depth and length components, and all three metrics are connected in the stream; if you used a subset of the residual pools, all metrics inherently include some information about depth. If you were to continue without deciding upon a metric, it would be too tempting to come up with post-hoc explanations (e.g., if sagittal area increased but not depth or length). You should certainly consider potential implications of your results (carefully), but in terms of evaluating the success of your project, it is important that you decide in advance which metric change = success.

Although it may be possible to run a MANOVA test (which can accommodate correlated dependent variables) using all three metrics together, MANOVA tests typically require larger sample sizes than we anticipate for many reach surveys. Therefore, we stick with multiple ANOVAs with a large dose of caution.

Assumption Robustness

Whenever applying statistical tests, we should ensure that our data is suitable, in that it meets the assumptions of the intended inferential test. For ANOVAs the assumptions are:

  • Data in different groups should be independent:

    • One of your sites must not cause changes in another (though both sites experiencing shared ‘external’ causal factors, such as being in the same watershed, is acceptable). This is hopefully accounted for by good selection of impact/control/reference sites.

    • You may note that no site is actually independent from that same site in the past. For longer time-series we would need to adopt a different inferential approach to avoid autocorrelation, but here we are dealing with simple before vs after comparisons, and it is widely accepted that ANOVAs are suitable for before/after comparisons if the comparison is balanced (e.g., 2 years of before data compared with 2 years of after data).

  • Residuals are normally distributed: In this case we mean residuals more broadly - the difference between each datapoint and the mean. We will examine this assumption using Q-Q plots and the Shapiro-Wilk normality test.

  • Homoscedasticity: Variance should be broadly equal across all groups. We will test this with Levene’s test.

If any of these assumptions are violated, we can transform the data and test whether the transformed data (log-, arcsine- etc.) satisfies the assumptions. If this is not an option, we should seek a more suitable statistical test (e.g. Welch’s ANOVA or mixed-effects models).

The tests of assumptions are carried out below, after we specify the before and after data that you wish to compare.

Before / After Years

Enter your before and after years in the below code, you may have more than one year in each category. Remember that these should balance (equal number of years before as after), but they need not be consecutive years. If you do not have balanced data (e.g., only one year was possible before project implementation) be very cautious in running and interpreting an ANOVA. You could select only a subset of your data to keep the comparison balanced, but if you do this for more than one set of dates you must account for the multiple comparisons inflating the likelihood of a Type I error (false positive).

# Define "Before" and "After" years
before_years <- c(2024) #add more years inside brackets if needed, e.g. 'c(2024, 2025, 2026)'
after_years <- c(2025) #add more years inside brackets if needed, e.g. 'c(2027, 2029, 2036)'

The next section of code generates tests and figures that you should review to ensure your data are suitable for an ANOVA. In brief, look for the following:

  • Boxplots: consider whether outliers (dots) are real or errors
  • Q-Q plots: a reasonably straight line of points means alignment with normal distribution
  • Normality test (Shapiro-Wilk): p<0.05 indicates non-normality
  • Levene’s test: p<0.05 indicates that variance among groups differs
  • Skewness values < 0 are left skewed, > 0 right skewed. Kurtosis values < 3 light-tailed, > 3 heavy-tailed.

Normality Test Results for Pool Summary Data
Site Time Category Max Residual Depth P-Value Sagittal Area P-Value Pool Length P-Value Message
Brousseau Channel After 0.700 0.346 0.507 Normality test completed
Hatchery Channel After 0.430 0.325 0.977 Normality test completed
Brousseau Channel Before 0.471 0.129 0.086 Normality test completed
Hatchery Channel Before 0.172 0.081 0.051 Normality test completed
## 
## --- Levene's Test Results for sagittal_area ---
## Levene's Test for Homogeneity of Variance (center = median)
##       Df F value   Pr(>F)   
## group  3  6.2061 0.002838 **
##       24                    
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## --- Levene's Test Results for max_residual_depth ---
## Levene's Test for Homogeneity of Variance (center = median)
##       Df F value  Pr(>F)  
## group  3  2.9027 0.05559 .
##       24                  
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## --- Levene's Test Results for pool_length ---
## Levene's Test for Homogeneity of Variance (center = median)
##       Df F value Pr(>F)
## group  3  1.7929 0.1754
##       24
##                              Variable  Skewness Kurtosis
## sagittal_area           sagittal_area 1.7710682 4.904845
## max_residual_depth max_residual_depth 0.8824034 2.069536
## pool_length               pool_length 1.3271828 4.412251

If, based on the above evaluation, your data appear to be unsuitable for the intended inferential test you may wish to use an alternative non-parametric test or transform the data. We provide some assistance for transformations here, but this part may require some more work on your part since we cannot predict what your data will need.

As an example, our data appeared normally distributed (p>0.05 Shapiro-Wilk) but Levene’s test revealed that sagittal area variance was unequal across site-years (p<0.05). We therefore log-transformed the sagittal area data and re-ran the above diagnostics, with Levene’s test returned as non-significant and therefore acceptable to be used in ANOVAs. Note that only those metrics that do not meet the assumptions need to be transformed.

The code we used for the transformation is below. If you need to transform the data, follow these steps:

Transformations

  1. Add your transformation(s) to the code chunk below. You must add a formula to calculate an appropriate transformation for each applicable variable within transformations <- list(…)). As an example, if you want to try a log transformation, replace ‘identity,’ in the below code with ‘function(x) ifelse(x > 0, log(x), NA),’

  2. Re-run the above diagnostics code after updating the applicable variable name(s) for each diagnostic test: where it says ‘variables <- c(“sagittal_area”, “max_residual_depth”, “pool_length”)’ you will update each applicable transformed variable name(s) to “transformed_variable_name”

  3. Once you have a transformed variable that meets the assumptions of the ANOVA, update the ANOVA inferential test code (in the subsequent code chunk) to use the “transformed_variable_name”

# Function to apply transformations and append to the dataframe
apply_transformations <- function(data, transformations) {
  for (var in names(transformations)) {
    transform_fn <- transformations[[var]]
    transformed_var <- paste0("transformed_", var)
    # Apply the transformation and append as a new column
    data[[transformed_var]] <- transform_fn(data[[var]])
  }
  return(data)
}

# Define transformations as a named list. You can add appropriate transformations here, then once you confirm the transformation is suitable, amend the anova code to call the correct variable

# Use 'identity' if no transformation is needed
transformations <- list(
  sagittal_area = identity, # example code fo log-transformation: replace 'identity,' with 'function(x) ifelse(x > 0, log(x), NA),' 
  max_residual_depth = identity,  # No transformation
  pool_length = identity # no transformation 
)

# Apply transformations and update the dataframe
pool_summary_filtered <- apply_transformations(pool_summary_filtered, transformations)

ANOVA

Once you have satisfied yourself that your data (or transformed data) are suitable, we will run the inferential tests. We use ANOVA to ask whether the following metrics differ among sites, years, and site*year interactions:

  • Sagittal area
  • Maximum residual depth
  • Pool length

If you did use transformed data, ensure you reference that variable in the below code (e.g., change “sagittal_area” to “transformed_sagittal_area”)

# Function to run ANOVA for a given variable
run_anova <- function(data, variable) {
  formula <- as.formula(paste(variable, "~ Site * Time_Category"))
  anova_result <- aov(formula, data = data)
  summary(anova_result)
}

# Ensure transformed data is used in the ANOVA if necessary (change the variable name in quotation marks in these next rows)
anova_max_residual_depth <- run_anova(pool_summary_filtered, "max_residual_depth")
anova_pool_length <- run_anova(pool_summary_filtered, "pool_length")
anova_sagittal_area <- run_anova(pool_summary_filtered, "sagittal_area")
## [1] "_______________ANOVA for Max Residual Depth______________"
##                    Df Sum Sq Mean Sq F value   Pr(>F)    
## Site                1  0.072   0.072   2.907   0.1011    
## Time_Category       1  3.712   3.712 150.194 8.07e-12 ***
## Site:Time_Category  1  0.115   0.115   4.642   0.0415 *  
## Residuals          24  0.593   0.025                     
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## [1] "_______________ANOVA for Residual Pool Length______________"
##                    Df Sum Sq Mean Sq F value  Pr(>F)   
## Site                1      6     6.0   0.038 0.84625   
## Time_Category       1   2022  2021.5  12.868 0.00148 **
## Site:Time_Category  1    163   163.4   1.040 0.31792   
## Residuals          24   3770   157.1                   
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## [1] "_______________ANOVA for Residual Pool Sagittal Area______________"
##                    Df Sum Sq Mean Sq F value   Pr(>F)    
## Site                1   31.6    31.6   0.675    0.419    
## Time_Category       1 1388.2  1388.2  29.659 1.35e-05 ***
## Site:Time_Category  1    6.3     6.3   0.134    0.718    
## Residuals          24 1123.3    46.8                     
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1

Take some time to ensure you understand what the above tells you, particularly with regards to your chosen metric of success. In the example ANOVA above, there was one site:time interaction that was significant at p=0.05 (maximum residual depth), and the time category was significant for all metrics. This suggests that a change in metrics over time was not likely due to chance, but only for maximum residual depth did our restoration site change over time differently than the control site. However, we chose sagittal area as our a priori success metric, so we cannot interpret this as a successful restoration action at this point in time.

Although we could not discard our alternative hypothesis (that changes at our restoration site were not due to our actions), we may still learn from the above to inform future plans. Consider all the information we have generated so far for you data, and take some time to think about it. Step outside to do this if you are able to. Consider what it might mean if pools at our restoration site appear deeper on average, but sagittal areas did not change? Consider whether there are pools that did or did not scrape through the subsetting cut-off (i.e., very small pools of marginal value), how might they impact your mean values? Was there a big enough change in these marginal cases to create statistical significance? Is any of this biologically or geomorphically meaningful based on your hypotheses?

This is all endlessly interesting/maddening (depending on your perspective) and we highly recommend finding another person (or several) to talk it through with. Before moving on to further analyses, ensure you have a reasonable understanding of the information so far. Take a step back to think about the big picture.

Volume Estimation

If you have no hypotheses or predictions specifically regarding pool volumes, you may wish to skip this section and move onto Fine Sediment in Pools.

If you took wetted width measurements at transects along the reach, you can use the average to estimate the volume of residual pools. This approach is a more simplified approach than that of Robison (1998) who linked wetted width measurements to nearby longitudinal intervals. If this is possible for the data you collected, we recommend reviewing Robison (1998) to obtain more ‘localised’ estimates of wetted width. However, bear in mind that there may regardless be a bias in residual wetted widths if (e.g.) pools tend to be wider than riffles. For our simplified approach we assume that the wetted width is constant for the reach, and we also assume that the stream cross sections are perfect triangles. We then use the ratio of residual depths to field-recorded depths to estimate the residual wetted widths of pools when flow approaches zero.

Considering changes in (coarsely-estimated) pool volume can be of interest due to the potential for natural processes to alter both the longitudinal and cross-sectional heterogeneity of a stream. For example, perhaps we are anticipating a narrower wetted channel with deeper pools, and want to explore what this means for pool volume. However, as suggested by the coarse assumptions we made for this calculation, interpret results with caution.

The above table lists the volume estimates for each of the ‘meaningful’ subset of residual pools, and this table is also exported to your output folder. Next we will display and export a table with some key summary statistics for the reach: Total volume of residual pools, and the mean and standard deviation residual volume of pools.

Inferential Tests - Volume

Following the same approach as for the one- and two-dimensional pool metrics, we will use ANOVAs to test the pool volume differences between sites and years.

Assumption Robustness

As before, the first step is to check whether an ANOVA is suitable for the variables.

Normality Test Results for Pool Volume Data
Site Time Category Pool Volume P-Value Message
Brousseau Channel After 0.500 Normality test completed
Hatchery Channel After 0.461 Normality test completed
Brousseau Channel Before 0.451 Normality test completed
Hatchery Channel Before 0.014 Normality test completed
## Levene's Test for Homogeneity of Variance (center = median)
##       Df F value   Pr(>F)   
## group  3  6.9518 0.001577 **
##       24                    
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1

## Skewness: 1.814195
## Kurtosis: 5.117599

We needed to transform our volume data, which was not normally distributed. Following the same transformation steps as before, We replaced ‘pool_volume_m3’ with the log-transformed ‘transformed_pool_volume_m3’ (using the below code) and re-ran the diagnostics. Our Q-Q plot and tests looked much better, so we used the transformed variable in the ANOVA.

# Define transformations as a named list for pool volume
transformations <- list(
  pool_volume_m3 = function(x) ifelse(x > 0, log(x), NA)  # Log transformation with handling for non-positive values (volumes should all be positive!)
)

# Apply transformations and update the dataframe
pool_volumes_filtered <- apply_transformations(pool_volumes_filtered, transformations)

ANOVA - volume

# Ensure transformed data is used in the ANOVA function if necessary (change the variable name in quotation marks)
anova_pool_volumes <- run_anova(pool_volumes_filtered, "pool_volume_m3") # adjust to "transformed_pool_volumes_m3" as needed
##                    Df Sum Sq Mean Sq F value   Pr(>F)    
## Site                1      4       4   0.014    0.907    
## Time_Category       1   9095    9095  33.011 6.39e-06 ***
## Site:Time_Category  1    231     231   0.839    0.369    
## Residuals          24   6613     276                     
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1

When interpreting potential changes in pool volume metrics, remember that we needed to make assumptions regarding the widths of residual pools, making these volume metrics more speculative than sagittal area metrics. While volumes can be useful for interpretation, if there are disagreements between the inferential test results among volume- and area/length-based metrics, we recommend defaulting to the latter (unless, of course, you have a solid a priori hypothesis and prediction that suggests volume should differ in the way you observed).

Fine Sediment in Pools

The longitudinal survey included presence/absence observations of fine sediment along the thalweg. Here we will generate a metric of the proportion of residual pool thalweg that features fine sediments.

Note that, while the previous metrics in this script use the ‘custom depth’ threshold to subset what are considered ‘meaningful’ pools, we recommend considering fine sediment relative to the full contingent of residual pools that the code has identified. Our rationale is that the fines metrics relate more closely to the mechanisms that can be responsible for making pools ‘meaningful’ (or not) in terms of fish habitat availability. If we were to look at the proportion of fines only in ‘meaningful’ (deep enough) pools, we might miss pools that are closer to being ‘not pools’ (i.e., recently filling-in or scouring of sediment). Of course, when pools are fully infilled with sediment they will not be detected as pools at all, but the ability to recognise when a pool is filling in (or scouring out) may be an important indicator of restoration success, or a trigger for adaptive management actions.

However, should it be of greater interest for your project, we have included in the code below the ability to select a subset of pools. Consistent with the previous custom depth threshold, you can add a specified depth in metres, or enter ‘NULL’ to select only pools with a maximum residual depth greater than the standard deviation of the residual depths for the entire sampled reach. Our default is 0 (no subsetting).

# Define custom threshold if required. We recommend 0 (all residual pools, regardless of maximum depth)
custom_depth <- 0  # Replace with your desired threshold in metres, or set to NULL to use the standard deviation of the reach (that year)
Brousseau Channel - Pool Fine Sediment
Site year pool_id pool_length fines_length fines_proportion
Brousseau Channel 2024 1 21.5 21.0 0.977
Brousseau Channel 2024 2 0.5 0.5 1.000
Brousseau Channel 2024 3 21.5 17.5 0.814
Brousseau Channel 2024 4 0.5 0.5 1.000
Brousseau Channel 2024 5 0.5 0.0 0.000
Brousseau Channel 2024 6 8.5 5.0 0.588
Brousseau Channel 2024 7 4.5 4.5 1.000
Brousseau Channel 2024 8 8.5 7.0 0.824
Brousseau Channel 2024 9 2.5 1.0 0.400
Brousseau Channel 2024 10 22.5 20.0 0.889
Brousseau Channel 2024 11 1.5 0.5 0.333
Brousseau Channel 2024 12 2.5 1.0 0.400
Brousseau Channel 2024 13 2.5 0.0 0.000
Brousseau Channel 2024 14 12.5 8.0 0.640
Brousseau Channel 2024 15 3.5 3.5 1.000
Brousseau Channel 2024 16 6.5 6.5 1.000
Brousseau Channel 2025 1 61.0 50.5 0.828
Brousseau Channel 2025 2 18.0 13.0 0.722
Brousseau Channel 2025 3 33.0 23.0 0.697
Brousseau Channel 2025 4 30.0 21.5 0.717
Brousseau Channel 2024 Total 120.0 96.5 0.804
Brousseau Channel 2025 Total 142.0 108.0 0.761
Hatchery Channel - Pool Fine Sediment
Site year pool_id pool_length fines_length fines_proportion
Hatchery Channel 2024 1 24.5 0.0 0.000
Hatchery Channel 2024 2 13.5 0.0 0.000
Hatchery Channel 2024 3 10.5 0.0 0.000
Hatchery Channel 2024 4 5.5 0.0 0.000
Hatchery Channel 2024 5 30.5 29.0 0.951
Hatchery Channel 2024 6 11.5 11.5 1.000
Hatchery Channel 2024 7 12.5 12.5 1.000
Hatchery Channel 2024 8 8.5 8.5 1.000
Hatchery Channel 2024 9 9.5 9.5 1.000
Hatchery Channel 2024 10 1.5 0.0 0.000
Hatchery Channel 2025 1 39.0 0.0 0.000
Hatchery Channel 2025 2 19.0 0.0 0.000
Hatchery Channel 2025 3 1.0 0.0 0.000
Hatchery Channel 2025 4 57.0 55.5 0.974
Hatchery Channel 2025 5 24.0 20.5 0.854
Hatchery Channel 2024 Total 128.0 71.0 0.555
Hatchery Channel 2025 Total 140.0 76.0 0.543

The above tables (also exported to output folder) include a final row for each site-year with reach total pool length, reach total pool length with fine sediment, and the reachwide proportion of pools with fines (a ratio from 0 to 1). Comparison of the reachwide proportion alone may be sufficient to demonstrate project effectiveness, perhaps complemented with the figure that we will create below. However, if you would like to statistically compare how fine sediment changed over time compared with a control, we can look at the distributions of underlying pool data (the fines_proportion data for every pool).

Inferential Tests - Fines

This time, we are dealing with data that are bounded by 0 and 1. And in many cases, we also anticipate a relatively high frequency of 0s (no fines in pools) and/or 1s (fines throughout). We are confident that non-transformed data would violate the assumptions of ANOVA, so we omit the initial diagnostic tests. Our attempts to arcsine-transform the data were not successful, as our transformed data remained non-normally distributed with significant heteroscedasticity. As such, and since we suspect our fines data distribution is not particularly unusual, we opted for Beta regression.

Slightly nerdy bit, feel free to ignore: Beta regressions are capable of dealing with non-normal heteroscedastic data. Although they cannot actually handle 0’s and 1’s, for our case they are preferable over two-part models (e.g. hurdle models): Since an observation of “no fine sediment” could very plausibly be recorded where 2 cm of fine sediment was actually present in a 20 m pool, we are comfortable adjusting the 0’s and 1’s to 0.001 and 0.999. We feel a hurdle model would excessively complicate interpretability (e.g. a binomial fines presence/absence mechanism plus a fines quantity mechanism). See Geissinger et al 2022 if interested.

We will generate a frequency plot of the fine proportion data, fit the Beta regression, and plot the frequency distribution of the residuals (which should be broadly symmetrical around zero) and their relationships to the fitted values (for which no clear relationship or heteroscedasticity should be evident). We will only export the results of the Beta regression to your output folder.

## Warning in betareg.fit(X, Y, Z, weights, offset, link, link.phi, type, control,
## : no valid starting value for precision parameter found, using 1 instead

## 
## Call:
## betareg(formula = fines_proportion_adjusted ~ Site * Time_Category, data = fines_proportion_filtered)
## 
## Quantile residuals:
##     Min      1Q  Median      3Q     Max 
## -1.6659 -0.7903  0.0613  1.0070  1.4205 
## 
## Coefficients (mean model with logit link):
##                                          Estimate Std. Error z value Pr(>|z|)
## (Intercept)                                0.2570     0.6770   0.380    0.704
## SiteHatchery Channel                      -0.9495     0.9034  -1.051    0.293
## Time_CategoryBefore                        0.1700     0.7544   0.225    0.822
## SiteHatchery Channel:Time_CategoryBefore   0.4271     1.0473   0.408    0.683
## 
## Phi coefficients (precision model with identity link):
##       Estimate Std. Error z value Pr(>|z|)    
## (phi)  0.52358    0.09579   5.466 4.61e-08 ***
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1 
## 
## Type of estimator: ML (maximum likelihood)
## Log-likelihood: 54.34 on 5 Df
## Pseudo R-squared: 0.1048
## Number of iterations: 20 (BFGS) + 2 (Fisher scoring)

Since you may not be familiar with Beta regression, here are some basics on interpretation for the test output:

  • “Optimization failed to converge…” If you see this warning, it may be that there were 0 values across an entire Site. This should be fairly easy to interpret without inferential tests.

  • Quantile residuals measure the difference between the actual data and predicted values. The median should be close to 0. Also check the residuals vs fitted plot to ensure there is no clear trend or unusual outliers

  • Coefficients (mean model): these are the effects of the predictors (site, time) on the response variable (fine sediment proportion in pools). Look for significant p values in the last column, particularly for the Site_____:Time_Category_____ row, which is the interaction term (if significant, this means the proportion of fines in residual pools changed over time differently between sites).

  • Phi coefficients: there is a p-value here as well, but this refers to whether the spread of the data around the mean was an important feature. If the phi estimate is very high, this means the data was concentrated around the mean (fines proportion doesn’t fluctuate much between sites/times). Consider phi of 0.1 to be spread out data, 1 to be moderate, and 10 to be concentrated around the mean.

  • Pseudo R-squared: this is how much of the variation in fines in pools can be explained by the site and time variables. Often low in ecological contexts.

Proportional data can be less intuitive to interpret, and using an unfamiliar inferential test might not clear things up. Not to worry: After we perform a similar analysis with the aquatic vegetation data, we will create some plots that show the distribution of fines and aquatics across the reach. These plots are more intuitive and will help you to interpret any changes in greater context.

Aquatic Vegetation in Pools

In the field, you may have also estimated the proportion of the wetted width that was occupied by aquatic vegetation. During data wrangling we added three new data columns to facilitate analyses of these aquatic vegetation observations: subveg (submerged vegetation), floatveg (floating vegetation), and emergveg (emergent vegetation). We will use these variables to estimate the length and plan area of each residual pool that would be occupied by aquatic vegetation when flows approach zero. These can be useful metrics for tracking habitat quality and mechanisms of habitat change, however plan area estimates come with a caveat:

In estimating plan areas of vegetation, we assume that the proportion of residual pool width occupied by vegetation is equal to the proportion of the wetted width that was occupied in the field. In most cases this will be an overestimate because the thalweg will typically have less vegetation and, as flows recede, the thalweg makes up a greater proportion of the wetted width. Although vegetated residual pool areas can be useful for tracking changes over time, because they are based on proportions of wetted widths, you should not consider them flow-independent. When interpreting changes over time (or from different reaches), remember that if flows were notably different, then the amount of submerged vegetation can differ. If you had the time/ability to collect wetted width measurements at each interval this could be used to control for this variation by adding it as a covariate in the inferential test. Otherwise, interpret with caution.

Aside from the above, in some cases it can also be difficult to assign proportions consistently in the field, such as when invasive reed canarygras forms dense mats that obscure banks and underlying soils/substrates. If there were such difficulties in the field, these should be clearly stated to aide interpretation. For the purposes of interpretation, remember that in this section we are considering the proportions of the length and the area of residual pools that are occupied by aquatic vegetation. As such, the field observations should relate to proportions of wetted width (not bankfull), because at flows approaching zero the vegetation between observed wetted width and bankfull width would not occupy any part of the residual pool.

🌿🌿🌿🌿🌿 🌿🌿🌿🌿🌿 🌿🌿🌿🌿🌿 🌿🌿🌿🌿🌿 🌿🌿🌿🌿🌿 🌿🌿🌿🌿🌿 🌿🌿🌿🌿🌿 🌿🌿🌿🌿🌿 🌿🌿🌿🌿🌿

The tables generated and exported by the code below will show the proportional length of residual pools in which aquatic vegetation was present (regardless of quantity/width), in the same way that we used the fines data. The tables also show the plan area of residual pools that featured aquatic vegetation, based on your estimates of the proportion of wetted width occupied by vegetation at each interval, integrated along the length of each pool.

Just like for fines, for aquatic vegetation we default to using the full contingent of pools. Our rationale is that vegetation (particularly certain problematic invasive species) can be involved in the process of infilling pools by trapping sediment, and it may be of restoration significance to track changes in vegetation in minor nascent or infilling pools. However, as before, we have included in the code below the ability to select a subset of pools, for example if you want to focus on factors such as the importance of aquatic vegetative cover that would plausibly be used by rearing fish in summer (i.e., only in pools of a certain depth). Our default is 0 (no subsetting), and if you change it, ensure that when comparing systems or years you are comparing like for like.

# Define custom threshold if required. We recommend 0 (all residual pools, regardless of maximum depth)
custom_depth <- 0  # Replace with your desired threshold in metres, or set to NULL to use the standard deviation of the reach (that year)
Reachwide Submerged Vegetation for Each Site-Year
site year pool_id pool_length veg_length veg_proportional_length veg_proportional_area
Brousseau Channel_2024_Total Brousseau Channel 2024 Total 128 0 0.0000000 0.0000000
Brousseau Channel_2025_Total Brousseau Channel 2025 Total 142 0 0.0000000 0.0000000
Hatchery Channel_2024_Total Hatchery Channel 2024 Total 133 112 0.8421053 0.8398496
Hatchery Channel_2025_Total Hatchery Channel 2025 Total 140 117 0.8357143 0.8321429
Reachwide Emergent Vegetation for Each Site-Year
site year pool_id pool_length veg_length veg_proportional_length veg_proportional_area
Brousseau Channel_2024_Total Brousseau Channel 2024 Total 128 0 0 0
Brousseau Channel_2025_Total Brousseau Channel 2025 Total 142 0 0 0
Hatchery Channel_2024_Total Hatchery Channel 2024 Total 133 0 0 0
Hatchery Channel_2025_Total Hatchery Channel 2025 Total 140 0 0 0
Reachwide Floating Vegetation for Each Site-Year
site year pool_id pool_length veg_length veg_proportional_length veg_proportional_area
Brousseau Channel_2024_Total Brousseau Channel 2024 Total 128 10 0.0781250 0.0781250
Brousseau Channel_2025_Total Brousseau Channel 2025 Total 142 10 0.0704225 0.0704225
Hatchery Channel_2024_Total Hatchery Channel 2024 Total 133 41 0.3082707 0.0748120
Hatchery Channel_2025_Total Hatchery Channel 2025 Total 140 43 0.3071429 0.0737500

Inferential Tests - Aquatic Veg

Just like with the fines data, we are dealing with data that are bounded by 0 and 1 (for both proportions of length and for area, across each type of vegetation). The non-transformed data would be expected to violate the assumptions of ANOVA, so we omit the initial diagnostic tests. We will again apply Beta regressions.

Below we display the Beta regression model summaries for all vegetation categories (where present), both length and area proportions. We omit the diagnostic plots from the display, but when you run the code for your data, you should examine the plots.

## 
## 
## 
## Model Summary for veg_proportional_length in subveg_result dataset:
## 
## Call:
## betareg(formula = response_adjusted ~ site * Time_Category, data = filtered_data)
## 
## Quantile residuals:
##     Min      1Q  Median      3Q     Max 
## -2.3441 -0.3019 -0.3019  0.4249  0.9525 
## 
## Coefficients (mean model with logit link):
##                                            Estimate Std. Error z value Pr(>|z|)
## (Intercept)                              -1.594e+00  6.142e-01  -2.596  0.00944
## siteHatchery Channel                      2.766e+00  8.791e-01   3.146  0.00166
## Time_CategoryBefore                      -8.473e-17  6.483e-01   0.000  1.00000
## siteHatchery Channel:Time_CategoryBefore -3.269e-01  9.353e-01  -0.350  0.72668
##                                            
## (Intercept)                              **
## siteHatchery Channel                     **
## Time_CategoryBefore                        
## siteHatchery Channel:Time_CategoryBefore   
## 
## Phi coefficients (precision model with identity link):
##       Estimate Std. Error z value Pr(>|z|)    
## (phi)   0.7401     0.1778   4.162 3.16e-05 ***
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1 
## 
## Type of estimator: ML (maximum likelihood)
## Log-likelihood: 113.4 on 5 Df
## Pseudo R-squared: 0.7103
## Number of iterations: 22 (BFGS) + 2 (Fisher scoring) 
## 
## 
## 
## Model Summary for veg_proportional_area in subveg_result dataset:
## 
## Call:
## betareg(formula = response_adjusted ~ site * Time_Category, data = filtered_data)
## 
## Quantile residuals:
##     Min      1Q  Median      3Q     Max 
## -2.3905 -0.3036 -0.3036  0.3115  1.0964 
## 
## Coefficients (mean model with logit link):
##                                            Estimate Std. Error z value Pr(>|z|)
## (Intercept)                              -1.661e+00  6.087e-01  -2.729  0.00635
## siteHatchery Channel                      2.498e+00  8.694e-01   2.873  0.00407
## Time_CategoryBefore                       2.271e-16  6.425e-01   0.000  1.00000
## siteHatchery Channel:Time_CategoryBefore -7.093e-02  9.408e-01  -0.075  0.93990
##                                            
## (Intercept)                              **
## siteHatchery Channel                     **
## Time_CategoryBefore                        
## siteHatchery Channel:Time_CategoryBefore   
## 
## Phi coefficients (precision model with identity link):
##       Estimate Std. Error z value Pr(>|z|)    
## (phi)   0.8011     0.1898    4.22 2.44e-05 ***
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1 
## 
## Type of estimator: ML (maximum likelihood)
## Log-likelihood: 103.4 on 5 Df
## Pseudo R-squared: 0.6998
## Number of iterations: 27 (BFGS) + 2 (Fisher scoring) 
## 
## Warning: optimization failed to converge for veg_proportional_length in emergveg_result dataset
## 
## 
## 
## No model convergence for veg_proportional_length in emergveg_result 
## 
## Warning: optimization failed to converge for veg_proportional_area in emergveg_result dataset
## 
## 
## 
## No model convergence for veg_proportional_area in emergveg_result 
## 
## 
## 
## Model Summary for veg_proportional_length in floatveg_result dataset:
## 
## Call:
## betareg(formula = response_adjusted ~ site * Time_Category, data = filtered_data)
## 
## Quantile residuals:
##     Min      1Q  Median      3Q     Max 
## -1.1733 -0.5225 -0.3722  0.0608  1.9359 
## 
## Coefficients (mean model with logit link):
##                                          Estimate Std. Error z value Pr(>|z|)
## (Intercept)                              -1.96714    0.59286  -3.318 0.000907
## siteHatchery Channel                      0.64810    0.74930   0.865 0.387073
## Time_CategoryBefore                      -0.16239    0.61162  -0.266 0.790619
## siteHatchery Channel:Time_CategoryBefore  0.06658    0.87227   0.076 0.939159
##                                             
## (Intercept)                              ***
## siteHatchery Channel                        
## Time_CategoryBefore                         
## siteHatchery Channel:Time_CategoryBefore    
## 
## Phi coefficients (precision model with identity link):
##       Estimate Std. Error z value Pr(>|z|)    
## (phi)   1.5015     0.4167   3.603 0.000314 ***
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1 
## 
## Type of estimator: ML (maximum likelihood)
## Log-likelihood: 91.44 on 5 Df
## Pseudo R-squared: 0.2478
## Number of iterations: 21 (BFGS) + 1 (Fisher scoring) 
## 
## 
## 
## Model Summary for veg_proportional_area in floatveg_result dataset:
## 
## Call:
## betareg(formula = response_adjusted ~ site * Time_Category, data = filtered_data)
## 
## Quantile residuals:
##     Min      1Q  Median      3Q     Max 
## -0.9762 -0.6076 -0.3915 -0.2771  2.7722 
## 
## Coefficients (mean model with logit link):
##                                          Estimate Std. Error z value Pr(>|z|)
## (Intercept)                               -3.0740     0.5594  -5.495  3.9e-08
## siteHatchery Channel                       0.3284     0.6659   0.493    0.622
## Time_CategoryBefore                       -0.2105     0.5587  -0.377    0.706
## siteHatchery Channel:Time_CategoryBefore   0.1576     0.7767   0.203    0.839
##                                             
## (Intercept)                              ***
## siteHatchery Channel                        
## Time_CategoryBefore                         
## siteHatchery Channel:Time_CategoryBefore    
## 
## Phi coefficients (precision model with identity link):
##       Estimate Std. Error z value Pr(>|z|)   
## (phi)    6.103      2.047   2.981  0.00288 **
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1 
## 
## Type of estimator: ML (maximum likelihood)
## Log-likelihood: 109.5 on 5 Df
## Pseudo R-squared: 0.1604
## Number of iterations: 23 (BFGS) + 2 (Fisher scoring)

Here is that basic interpretation assistance from before, but also remember that there is extra nuance now you are dealing with proportions of pool length or proportion of pool plan area.

  • “Optimization failed to converge…” If you see this warning, it may be that there were 0 values across an entire Site. This should be fairly easy to interpret without inferential tests.

  • Quantile residuals measure the difference between the actual data and predicted values. The median should be close to 0. Also check the residuals vs fitted plot to ensure there is no clear trend or unusual outliers

  • Coefficients (mean model): these are the effects of the predictors (site, time) on the response variable (fine sediment proportion in pools). Look for significant p values in the last column, particularly for the Site_____:Time_Category_____ row, which is the interaction term (if significant, this means the proportion of fines in residual pools changed over time differently between sites).

  • Phi coefficients: there is a p-value here as well, but this refers to whether the spread of the data around the mean was an important feature. If the phi estimate is very high, this means the data was concentrated around the mean (fines proportion doesn’t fluctuate much between sites/times). Consider phi of 0.1 to be spread out data, 1 to be moderate, and 10 to be concentrated around the mean.

  • Pseudo R-squared: this is how much of the variation in fines in pools can be explained by the site and time variables. Often low in ecological contexts.

Next up are the promised plots that show the distribution of fines and aquatics across the reach, which should facilitate interpretation.

Composite Figure

This figure juxtaposes the plots showing the residual surfaces with the presence/absence record of fine sediments, and with the wetted width proportion of the three categories of aquatic vegetation. Where factors like excess sedimentation, eutrophication, invasive aquatics, excessively fluctuating dissolved oxygen, and/or lack of pool habitat is a concern, this figure should be useful to visually compare reaches or track changes over time.

Remember that in a BACI study our primary interest is whether our restoration site changed in a different way than the control/reference sites changed across time - this is not always easy to see in figures, so consider the figure alongside the inferential test results from above. Bear in mind that the figure presents data by year whereas our inferential tests consider before vs after time categories.

If you have several sites/years, you can modify the code below to choose which figures are plotted in RStudio. If left at NULL site and NULL year, the code will display all site-years in one composite figure. You can alter this code to display one year for one site, all years for one site, or all sites for one year.

Regardless of what you view in RStudio, the code will export all individual site-year plots and the full composite figure as html files to your output folder.

# User-defined site and year for individual plot display
selected_site <- NULL # Replace with the desired "site name" (include the quotation marks) or use NULL for all sites
selected_year <- NULL # Replace with the desired year (no brackets) or use NULL for all years

Now that you have visualisations of the residual pool data, and statistical tests to examine the statistical significance of differences in reach pool characteristics among reaches and years, it is time to consider the biological/morphological significance and the implications for your project.

Next Steps

We can now move on to looking at a few more components of habitat that may be useful to monitor for your project. We will export the residual pool data we generated in this code for use later on (when considering habitat unit classifications). This will be exported to your output folder (which by now, might be a bit busy. If moving files around, remember that the html files need to be in the same folder as their similarly-named dependency folders).

References

Clark, C., Roni, P. and Burgess, S., 2019. Response of juvenile salmonids to large wood placement in Columbia River tributaries. Hydrobiologia, 842(1), pp.173-190.

Geissinger, E.A., Khoo, C.L., Richmond, I.C., Faulkner, S.J. and Schneider, D.C., 2022. A case for beta regression in the natural sciences. Ecosphere, 13(2), p.e3940.

Kaufmann, P.R., Levine, P., Peck, D.V., Robison, E.G. and Seeliger, C., 1999. Quantifying physical habitat in wadeable streams (p. 149). USEPA [National Health and Environmental Effects Research Laboratory, Western Ecology Division].

Lisle, T.E., 1986. Effects of woody debris on anadromous salmonid habitat, Prince of Wales Island, southeast Alaska. North American Journal of Fisheries Management, 6(4), pp.538-550.

Lisle, T.E., 1987. Using” residual depths” to monitor pool depths independently of discharge. Res. Note PSW-RN-394. Berkeley, CA: US Department of Agriculture, Forest Service, Pacific Southwest Forest and Range Experiment Station. 4 p, 394.

Mossop, B. and Bradford, M.J., 2006. Using thalweg profiling to assess and monitor juvenile salmon (Oncorhynchus spp.) habitat in small streams. Canadian Journal of Fisheries and Aquatic Sciences, 63(7), pp.1515-1525.

Robison, E.G., 1998. Reach scale sampling metrics and longitudinal pattern adjustment of small streams. PhD Thesis. Oregon State University.

Stack, W.R., 1988. Factors influencing pool morphology in Oregon coastal streams. MSc Thesis. Oregon State University

LS0tDQp0aXRsZTogIkxvbmdpdHVkaW5hbCBTdXJ2ZXkgMyBSZXNpZHVhbCBQb29scyINCmF1dGhvcjogIk9saXZlciBGcmFua2xpbiAmIE5pY2NpIFphcmdhcnBvdXIiDQpkYXRlOiAiYHIgU3lzLkRhdGUoKWAiDQpvdXRwdXQ6IA0KICBodG1sX2RvY3VtZW50Og0KICAgIGNvZGVfZG93bmxvYWQ6IHRydWUNCi0tLQ0KDQpgYGB7ciBzZXR1cCwgaW5jbHVkZT1GQUxTRX0NCmtuaXRyOjpvcHRzX2NodW5rJHNldChmaWcud2lkdGg9MTIsIGZpZy5oZWlnaHQ9OSwgZWNobyA9IFRSVUUpDQppZiAoIXJlcXVpcmVOYW1lc3BhY2UoInBhY21hbiIsIHF1aWV0bHkgPSBUUlVFKSkgew0KICBpbnN0YWxsLnBhY2thZ2VzKCJwYWNtYW4iKX0NCnBhY21hbjo6cF9sb2FkKERULCB0aWR5dmVyc2UsIGRwbHlyLCB0aWR5ciwgZ2dwbG90Miwga25pdHIsIGthYmxlRXh0cmEsIGdyaWRFeHRyYSwgY293cGxvdCwgY2FyLCBtb21lbnRzLCBwbG90bHksIGh0bWx0b29scywgaHRtbHdpZGdldHMsIHRpYmJsZSwgYmV0YXJlZywgdXBkYXRlPUYpDQpgYGANCg0KYGBge3IgZXhwb3J0IGZ1bmN0aW9ucyBhbmQgZm9sZGVyLCBlY2hvID0gRkFMU0V9DQojIGZ1bmN0aW9ucyB0byB1c2UgZm9yIGV4cG9ydGluZyByZXN1bHRzIHRvIG91dHB1dF9mb2xkZXIgKHdoaWNoIGlzIHByb21wdGVkIGluIFIgd2hlbiBub3QgaW4gUiBlbnZpcm9ubWVudCkNCg0KI2V4cG9ydCBmaWd1cmUgKHBkZiBmb3Igc3RhdGljIGdncGxvdCBwbG90cywgaHRtbCBmb3IgaW50ZXJhY3RpdmUgcGxvdGx5IHBsb3RzKQ0KZXhwb3J0X3Bsb3QgPC0gZnVuY3Rpb24ocGxvdCwgZmlsZW5hbWUpIHsNCiAgaWYgKGluaGVyaXRzKHBsb3QsICJnZ3Bsb3QiKSkgew0KICAgICMgRXhwb3J0IGdncGxvdCBhcyBQREYNCiAgICBnZ3NhdmUoDQogICAgICBmaWxlbmFtZSA9IGZpbGUucGF0aChvdXRwdXRfZm9sZGVyLCBmaWxlbmFtZSksDQogICAgICBwbG90ID0gcGxvdCwNCiAgICAgIGRldmljZSA9ICJwZGYiLA0KICAgICAgd2lkdGggPSAxMSwNCiAgICAgIGhlaWdodCA9IDguNQ0KICAgICkNCiAgfSBlbHNlIGlmIChpbmhlcml0cyhwbG90LCAicGxvdGx5IikpIHsNCiAgICAjIEVuc3VyZSB0aGUgZmlsZW5hbWUgaGFzIC5odG1sIGV4dGVuc2lvbg0KICAgIGh0bWxfZmlsZW5hbWUgPC0gZmlsZS5wYXRoKG91dHB1dF9mb2xkZXIsIHN1YigiXFwucGRmJCIsICIuaHRtbCIsIGZpbGVuYW1lKSkNCiAgICAjIEV4cG9ydCBwbG90bHkgYXMgYSAqKnNpbmdsZSBzZWxmLWNvbnRhaW5lZCoqIEhUTUwgZmlsZQ0KICAgIHNhdmVXaWRnZXQoDQogICAgICB3aWRnZXQgPSBwbG90LCANCiAgICAgIGZpbGUgPSBodG1sX2ZpbGVuYW1lLCANCiAgICAgIHNlbGZjb250YWluZWQgPSBUUlVFICAjIA0KICAgICkNCiAgfSBlbHNlIHsNCiAgICBzdG9wKCJVbnN1cHBvcnRlZCBwbG90IHR5cGUuIE9ubHkgZ2dwbG90IGFuZCBwbG90bHkgb2JqZWN0cyBhcmUgc3VwcG9ydGVkLiIpDQogIH0NCn0NCg0KIyBGdW5jdGlvbiB0byBzYXZlIGEgdGFibGUNCmV4cG9ydF90YWJsZSA8LSBmdW5jdGlvbih0YWJsZSwgZmlsZW5hbWUpIHsNCiAgd3JpdGUuY3N2KA0KICAgIHRhYmxlLA0KICAgIGZpbGUgPSBmaWxlLnBhdGgob3V0cHV0X2ZvbGRlciwgZmlsZW5hbWUpLA0KICAgIHJvdy5uYW1lcyA9IEZBTFNFDQogICkNCn0NCg0KIyBGdW5jdGlvbiB0byBzYXZlIHN1bW1hcnkgYXMgdHh0DQpleHBvcnRfc3VtbWFyeSA8LSBmdW5jdGlvbihzdW1tYXJ5X3RleHQsIGZpbGVuYW1lX2Jhc2UpIHsNCiAgIyBFbnN1cmUgc3VtbWFyeV90ZXh0IGlzIGEgY2hhcmFjdGVyIHZlY3RvciAoaXQgc2hvdWxkIGFscmVhZHkgYmUsIGJ1dCBqdXN0IGluIGNhc2UpDQogIHN1bW1hcnlfdGV4dCA8LSBhcy5jaGFyYWN0ZXIoc3VtbWFyeV90ZXh0KQ0KICAgICMgU2F2ZSBhcyAudHh0DQogIHR4dF9wYXRoIDwtIGZpbGUucGF0aChvdXRwdXRfZm9sZGVyLCBwYXN0ZTAoZmlsZW5hbWVfYmFzZSwgIi50eHQiKSkNCiAgd3JpdGVMaW5lcyhzdW1tYXJ5X3RleHQsIGNvbiA9IHR4dF9wYXRoKQ0KfQ0KDQojIEV4YW1wbGVzIG9mIGV4cG9ydGluZyBpbmRpdmlkdWFsIHJlc3VsdHM6DQojIEV4cG9ydCBhIGZpZ3VyZQ0KIyBleHBvcnRfcGxvdChnZ3Bsb3RfcGxvdCwgIlRoYWx3ZWcgV2F0ZXIgRGVwdGggYnkgRGlzdGFuY2UgVXBzdHJlYW0ucGRmIikNCiMgZXhwb3J0X3Bsb3QocGxvdGx5X3Bsb3QsICJUaGFsd2VnIFdhdGVyIERlcHRoIGJ5IERpc3RhbmNlIFVwc3RyZWFtLmh0bWwiKQ0KIyANCiMgIyBFeHBvcnRpbmcgYSB0YWJsZQ0KIyBzdW1tYXJ5X3RhYmxlIDwtIHN1bW1hcnkobXRjYXJzKQ0KIyBleHBvcnRfdGFibGUoYXMuZGF0YS5mcmFtZShzdW1tYXJ5X3RhYmxlKSwgInN1bW1hcnlfdGFibGUuY3N2IikNCiMgDQojIEV4YW1wbGUgb2YgZXhwb3J0aW5nIGEgc3VtbWFyeQ0KIyBzdW1tYXJ5X3RleHQgPC0gY2FwdHVyZS5vdXRwdXQoc3VtbWFyeShtdGNhcnMpKQ0KIyBleHBvcnRfc3VtbWFyeShzdW1tYXJ5X3RleHQsICJzdW1tYXJ5IikNCg0KIyBiZWxvdyBjb2RlIHRvIGNvbmZpcm0gYW4gb3V0cHV0IGZvbGRlciBpcyBhbHJlYWR5IHNwZWNpZmllZCwgT1Igd2lsbCByZXF1ZXN0IGl0IGlzIHNwZWNpZmllZCBpbiBSIChpbnRlcmFjdGl2ZWx5IHZpYSByZWFkbGluZSkNCiMgQlVUIGlmIHlvdSB3YW50IHRvIGtuaXQsIHlvdSB3aWxsIG5lZWQgdG8gc3BlY2lmeSBhIGRlZmF1bHQgbG9jYXRpb24gKHdpdGhpbiB0aGUgJ2Vsc2UnIHRlcm0pDQppZiAoaW50ZXJhY3RpdmUoKSkgew0KICB3aGlsZSAoIWV4aXN0cygib3V0cHV0X2ZvbGRlciIpIHx8ICFkaXIuZXhpc3RzKG91dHB1dF9mb2xkZXIpKSB7DQogICAgb3V0cHV0X2ZvbGRlciA8LSByZWFkbGluZShwcm9tcHQgPSAiU3BlY2lmeSB0aGUgb3V0cHV0IGZvbGRlcjogIikNCiAgICBpZiAoIWRpci5leGlzdHMob3V0cHV0X2ZvbGRlcikpIHsNCiAgICAgIHRyeUNhdGNoKHsNCiAgICAgICAgZGlyLmNyZWF0ZShvdXRwdXRfZm9sZGVyLCByZWN1cnNpdmUgPSBUUlVFKQ0KICAgICAgICBtZXNzYWdlKCJDcmVhdGVkIGZvbGRlcjogIiwgb3V0cHV0X2ZvbGRlcikNCiAgICAgIH0sIGVycm9yID0gZnVuY3Rpb24oZSkgew0KICAgICAgICBtZXNzYWdlKCJJbnZhbGlkIGZvbGRlci4gUGxlYXNlIHRyeSBhZ2Fpbi4iKQ0KICAgICAgICBvdXRwdXRfZm9sZGVyIDwtIE5VTEwNCiAgICAgIH0pDQogICAgfQ0KICB9DQp9IGVsc2Ugew0KICAjIFNwZWNpZnkgYSBkZWZhdWx0IGZvbGRlciBmb3Igbm9uLWludGVyYWN0aXZlIG1vZGUgKGUuZy4sIGtuaXR0aW5nKQ0KICBvdXRwdXRfZm9sZGVyIDwtICJ+L0dpdC9Db3JlIE1vbml0b3Jpbmcvc3RhbmRhcmRpc2VkIHByb3RvY29scy9kYXRhX3RpZGllci9Mb25naXR1ZGluYWwiDQogIGlmICghZGlyLmV4aXN0cyhvdXRwdXRfZm9sZGVyKSkgew0KICAgIGRpci5jcmVhdGUob3V0cHV0X2ZvbGRlciwgcmVjdXJzaXZlID0gVFJVRSkNCiAgICBtZXNzYWdlKCJEZWZhdWx0IG91dHB1dCBmb2xkZXIgY3JlYXRlZDogIiwgb3V0cHV0X2ZvbGRlcikNCiAgfQ0KfQ0KYGBgDQoNCkluIHRoaXMgc2NyaXB0IHdlIGVzdGltYXRlIHJlc2lkdWFsIHBvb2wgY2hhcmFjdGVyaXN0aWNzLiBUaGUgcmVzaWR1YWwgcG9vbCBpcyB0aGUgcG9vbCB0aGF0IHdvdWxkIGZvcm0gaWYgc3RyZWFtZmxvdyB3ZXJlIHRvIGRlY3JlYXNlIHRvIHplcm8uIEl0cyBkZXB0aCBpcyBjaGFyYWN0ZXJpc2VkIGFzIHRoZSBlbGV2YXRpb24gZGlmZmVyZW5jZSBiZXR3ZWVuIHRoZSBwb29sJ3MgZGVlcGVzdCBwb2ludCBhbmQgdGhlIHBvb2wgb3V0bGV0IC8gcmlmZmxlIGNyZXN0IHRoYXQgY29udHJvbHMgdGhlIGZsb3cgb2Ygd2F0ZXIgb3V0IG9mIHRoZSBwb29sLiBJdCBzZXJ2ZXMgYXMgYSBmbG93LWluZGVwZW5kZW50IG1ldHJpYyBvZiBwb29scyBpbiBhIHN0cmVhbSBhbmQsIHdpdGggc2V2ZXJhbCBhc3N1bXB0aW9ucywgd2UgY2FuIGVzdGltYXRlIHRoZSBkZXB0aHMsIGFyZWFzLCBhbmQgdm9sdW1lcyBvZiByZXNpZHVhbCBwb29scyBiYXNlZCBvbiBvdXIgZmllbGQgZGF0YS4gU2VlIExpc2xlICgxOTg5KSBmb3IgbW9yZSBiYWNrZ3JvdW5kIG9uIHRoZSBjb25jZXB0IG9mIHJlc2lkdWFsIGRlcHRocy4NCg0KV2UgdHJpZWQgdG8gbWFrZSBmaWVsZCBkYXRhIGNvbGxlY3Rpb24gYXMgc2ltcGxlIGFzIHBvc3NpYmxlIGJ5IHJlbHlpbmcgb24gd2F0ZXIgZGVwdGhzIHJhdGhlciB0aGFuIGVsZXZhdGlvbnMgZm9yIG91ciBsb25naXR1ZGluYWwgcHJvZmlsZXMsIHNvIHRoYXQgcGVvcGxlIGNvdWxkIGNvbGxlY3QgZGF0YSB3aXRob3V0IHN1cnZleSBlcXVpcG1lbnQgLSByZWR1Y2luZyB0aGUgY29zdCBhbmQgZXhwZXJ0aXNlIHJlcXVpcmVkLCBhbmQgZmFjaWxpdGF0aW5nIGFzc2Vzc21lbnQgaW4gZGVuc2VseSB2ZWdldGF0ZWQgLyB3b29keSBjb2FzdGFsIHN0cmVhbXMsIGhpZ2hseSBpbmNpc2VkIGNoYW5uZWxzIGV0Yy4gVGhlIHVzZSBvZiBzaW1wbGUgZGVwdGggZGF0YSByZXF1aXJlcyBhIGNvdXBsZSBvZiBleHRyYSBwcm9jZXNzaW5nIHN0ZXBzIGNvbXBhcmVkIHdpdGggdXNpbmcgZWxldmF0aW9uIGRhdGEsIGJ1dCBsdWNraWx5IHNvbWUgcmF0aGVyIGNsZXZlciBpbmRpdmlkdWFscyBoYXZlIGFscmVhZHkgZmlndXJlZCBpdCBvdXQuIA0KDQpUaGUgY29kZSB3ZSB1c2UgaGVyZSBpcyBhZGFwdGVkIGZyb20gdGhlICdSYXBpZCBCZWQgUHJvZmlsZScgYXBwcm9hY2ggZnJvbSBTdGFjayAoMTk4OSksIHdpdGggYWRkaXRpb25hbCBndWlkYW5jZSBmcm9tIEthdWZtYW4gZXQgYWwuICgxOTk5KSwgYW5kIHdlIGFkb3B0IFN0YWNrJ3Mgc2xvcGUgZmFjdG9yLiBUaGUgc2xvcGUgZmFjdG9yIHdhcyBkZXZlbG9wZWQgaW4gY29hc3RhbCBzdHJlYW1zIGJ1dCBoYXMgYmVlbiBhcHBsaWVkIHN1Y2Nlc3NmdWxseSBpbiBhIHZhcmlldHkgb2Ygb3RoZXIgc3lzdGVtcy4gSWYgeW91IGhhdmUgdGhlIHJlc291cmNlcywgdGhlIGFjY3VyYWN5IG9mIHRoZSBzbG9wZSBmYWN0b3IgZm9yIHlvdXIgcGFydGljdWxhciBzeXN0ZW0gY2FuIGJlIHRlc3RlZCBieSBjb21wYXJpbmcgd2F0ZXItZGVwdGgtZGVyaXZlZCB0byBlbGV2YXRpb24tZGVyaXZlZCByZXNpZHVhbCBwb29sIGRhdGEuIEhvd2V2ZXIsIGV2ZW4gaWYgdGhpcyBhc3N1bXB0aW9uIGlzIHVudGVzdGVkIChhcyBpdCB3aWxsIGJlIGluIG1vc3QgY2FzZXMpLCB0aGUgcmVzdWx0aW5nIG1ldHJpY3MgcmVtYWluIHZhbGlkIGZvciBhc3Nlc3NpbmcgY2hhbmdlcyB3aXRoaW4gYSBzeXN0ZW0sIGFzIGxvbmcgYXMgeW91IGRvbid0IGNoYW5nZSB0aGUgc2xvcGUgZmFjdG9yIGJldHdlZW4geWVhcnMgb3IgcmVhY2hlcyBpbiB5b3VyIGNvbXBhcmlzb24uDQoNCiMgRGF0YSBpbXBvcnQNCg0KRmlyc3Qgd2Ugd2lsbCBpbXBvcnQgdGhlIHRpZGllZCBkYXRhZnJhbWUgZ2VuZXJhdGVkIGJ5IHRoZSBEYXRhIFdyYW5nbGluZyBzY3JpcHQsIHdoaWNoIHdhcyBleHBvcnRlZCB0byB5b3VyIG91dHB1dCBmb2xkZXIuIFRoaXMgZmlsZSBoYXMgbG9uZ2l0dWRpbmFsIHRoYWx3ZWcgd2F0ZXIgZGVwdGggZGF0YSB0aGF0IGluY2x1ZGVzIGJvdGggcmVndWxhciBwcmVkZXRlcm1pbmVkIHNwYWNpbmcgYW5kIGFueSAnZXh0cmEnIHBvb2wgb3V0bGV0cyBhbmQgbWF4IHBvb2wgZGVwdGhzIGVuY291bnRlcmVkICgnWFBPJywgJ1hEJykuIFdlIHByb3Bvc2VkIHRoYXQgdGhlICdleHRyYScgbWVhc3VyZW1lbnRzIHdlcmUgdGFrZW4gaW4gdGhlIGZpZWxkLCBpbiBvcmRlciB0byBjYXB0dXJlIHRoZSBkZXB0aCBtaW5pbWEgKHBvdGVudGlhbCBwb29sIG91dGxldHMpIGFuZCBtYXhpbWEgKGRlZXBlc3QgcG9vbCBzZWN0aW9ucykgdGhhdCBtaWdodCBvY2N1ciBiZXR3ZWVuIHJlZ3VsYXIgaW50ZXJ2YWxzLg0KDQpgYGB7ciBpbXBvcnQgZGF0YSwgZWNobz1GQUxTRX0NCmltcG9ydGVkZGF0YSA8LSBmaWxlLnBhdGgob3V0cHV0X2ZvbGRlciwgIkxvbmdfZGF0YWZyYW1lLmNzdiIpDQpkZiA8LSByZWFkLmNzdihpbXBvcnRlZGRhdGEpICANCg0KIyMgaWYgeW91IG5lZWQgdG8gc3BlY2lmeSBhIGRpZmZlcmVudCBsb2NhdGlvbiB0byBpbXBvcnQgZnJvbSwgdXNlIGJlbG93IGNvZGU6DQojIGltcG9ydGVkZGF0YTwtcmVhZC5jc3YoIn4vR2l0L0NvcmUgTW9uaXRvcmluZy9zdGFuZGFyZGlzZWQgcHJvdG9jb2xzL2RhdGFfdGlkaWVyL0xvbmdpdHVkaW5hbC9Mb25nX2RhdGFmcmFtZS5jc3YiKSAjIHNwZWNpZnkgeW91ciBmaWxlIGxvY2F0aW9uICYgbmFtZSBoZXJlDQojIGRmPC1kYXRhLmZyYW1lKGltcG9ydGVkZGF0YSkNCmBgYA0KDQpJbiB0aGlzIGNvZGUgd2Ugd2lsbCByZXF1aXJlIHNvbWUgYWRkaXRpb25hbCBjb25zdGFudHMgdGhhdCB3ZSBhc2sgeW91IHRvIGRlZmluZSBpbiB0aGUgY29kZSBiZWxvdyBiYXNlZCBvbiBkYXRhIHlvdSByZWNvcmRlZCBpbiB0aGUgZmllbGQgKG9yIGFyZSBhYmxlIHRvIGVzdGltYXRlKS4gVGhpcyBpcyBkb25lIGJ5IGNyZWF0aW5nIGEgZGF0YWZyYW1lL3RhYmxlLCBmb3Igd2hpY2ggeW91IG11c3QgZW50ZXIgdGhlIGZvbGxvd2luZzoNCg0KLSBuYW1lcyBvZiBlYWNoIGNoYW5uZWwNCi0gdGhlIHllYXJzIGRhdGEgd2VyZSBjb2xsZWN0ZWQNCi0gdGhlIHN0YW5kYXJkIGludGVydmFsIHNwYWNpbmcgKGluIG1ldHJlcykgZm9yIGVhY2ggcmVhY2ggYW5kIGVhY2ggeWVhcg0KLSB0aGUgYXZlcmFnZSByZWFjaCBzbG9wZSAoMC41ID0gMC41JSwgbm90IDUwJSkgZm9yIGVhY2ggcmVhY2ggYW5kIGVhY2ggeWVhcg0KLSB0aGUgYXZlcmFnZSB3ZXR0ZWQgd2lkdGggZHVyaW5nIGxvdyBmbG93IChpbiBtZXRyZXMpIGZvciBlYWNoIHJlYWNoIGFuZCBlYWNoIHllYXIuDQoNCkVudGVyIHRoaXMgaW5mb3JtYXRpb24gaW4gdGhlIGNvZGUgYmVsb3cuIERhdGEgaXMgZW50ZXJlZCBpbiB2ZWN0b3JzIG9mIGVxdWFsIGxlbmd0aCBhbmQgZm9sbG93aW5nIHRoZSBzYW1lIHNlcXVlbmNlLiBGb3IgZXhhbXBsZSwgaW4gdGhlIGV4aXN0aW5nIGNvZGUsIEhhdGNoZXJ5IENoYW5uZWwgaXMgYXNzb2NpYXRlZCB3aXRoIHNwYWNpbmcgb2YgMSBhbmQgMSwgc2xvcGUgb2YgMSBhbmQgMS4xLCBhbmQgd2V0dGVkIHdpZHRoIG9mIDYuOCBhbmQgNy4wLCBmb3IgMjAyNCBhbmQgMjAyNSByZXNwZWN0aXZlbHkuDQpPbmNlIHlvdSBjcmVhdGUgdGhlIGRhdGFmcmFtZSB3aXRoIHlvdXIgZGF0YSwgY2hlY2sgdGhyb3VnaCB0aGUgdGFibGUgdG8gZW5zdXJlIHRoZXNlIGNvbnN0YW50cyBhcmUgYXNzaWduZWQgdG8gdGhlIGNvcnJlY3QgcmVhY2ggJiB5ZWFyLg0KDQpgYGAge3IgaW5wdXQgY29uc3RhbnRzfQ0KIyBDcmVhdGUgYSBkYXRhIGZyYW1lIHRvIGhvbGQgY29uc3RhbnRzIGZvciBtdWx0aXBsZSBzaXRlcyBhbmQgeWVhcnMuIEVudGVyIHlvdXIgZGF0YSBiZWxvdzoNCmNvbnN0YW50c19kZiA8LSBkYXRhLmZyYW1lKA0KICBTaXRlID0gYygiSGF0Y2hlcnkgQ2hhbm5lbCIsICJIYXRjaGVyeSBDaGFubmVsIiwgIkJyb3Vzc2VhdSBDaGFubmVsIiwgIkJyb3Vzc2VhdSBDaGFubmVsIiksICAjIEVkaXQgLyBBZGQgeW91ciBzaXRlIG5hbWVzDQogIHllYXIgPSBjKDIwMjQsIDIwMjUsIDIwMjQsIDIwMjUpLCAgIyBDb3JyZXNwb25kaW5nIHllYXJzIGZvciBlYWNoIHNpdGUNCiAgc3BhY2luZyA9IGMoMSwgMSwgMSwgMSksICAjIHNwYWNpbmcgdmFsdWVzIGZvciBlYWNoIHNpdGUteWVhciBjb21iaW5hdGlvbg0KICBTbG9wZSA9IGMoMC41LCAwLjYsIDAuNSwgMC41KSwgICAgIyBTbG9wZSB2YWx1ZXMgZm9yIGVhY2ggc2l0ZS15ZWFyIGNvbWJpbmF0aW9uLCBpbiAlDQogIFdldFdpZHRoID0gYyg2LjgsIDcuMCwgNi41LCA3LjEpICAjIEF2ZXJhZ2Ugd2V0dGVkIHdpZHRoIGluIG0sIGZvciBlYWNoIHNpdGUteWVhciBjb21iaW5hdGlvbg0KKQ0KDQojIFZpZXcgdGhlIGNvbnN0YW50cyBkYXRhIGZyYW1lDQpwcmludChjb25zdGFudHNfZGYpDQpgYGANCg0KYGBge3IgY29uc3RhbnQgZXh0cmFjdCBmdW5jdGlvbiwgZWNobyA9IEZBTFNFfQ0KIyBGdW5jdGlvbiB0byBnZXQgY29uc3RhbnRzIGZvciBhIHNwZWNpZmljIFNpdGUgYW5kIHllYXINCmdldF9jb25zdGFudHMgPC0gZnVuY3Rpb24oc2l0ZSwgeWVhcikgew0KICBjb25zdGFudHNfcm93IDwtIGNvbnN0YW50c19kZltjb25zdGFudHNfZGYkU2l0ZSA9PSBzaXRlICYgY29uc3RhbnRzX2RmJHllYXIgPT0geWVhciwgXQ0KICANCiAgaWYgKG5yb3coY29uc3RhbnRzX3JvdykgPT0gMCkgew0KICAgIHN0b3AocGFzdGUoIk5vIGNvbnN0YW50cyBmb3VuZCBmb3IgU2l0ZToiLCBzaXRlLCAieWVhcjoiLCB5ZWFyKSkNCiAgfQ0KICAgIA0KICAjIEV4dHJhY3QgY29uc3RhbnRzDQogIHNwYWNpbmcgPC0gY29uc3RhbnRzX3JvdyRzcGFjaW5nDQogIHNsb3BlIDwtIGNvbnN0YW50c19yb3ckU2xvcGUNCiAgd2V0d2lkdGggPC0gY29uc3RhbnRzX3JvdyRXZXRXaWR0aA0KICANCiAgcmV0dXJuKGxpc3Qoc3BhY2luZyA9IHNwYWNpbmcsIHNsb3BlID0gc2xvcGUsIHdldHdpZHRoID0gd2V0d2lkdGgpKQ0KfQ0KYGBgDQoNCiMgQ3JlYXRpb24gb2YgUmVzaWR1YWwgU3VyZmFjZXMNCg0KYGBge3IgY3JlYXRlIGFydGlmaWNpYWwgbmlja3BvaW50cywgZWNobyA9IEZBTFNFfQ0KIyBBbHRob3VnaCB3ZSByZWNvbW1lbmRlZCBzdGFydGluZyB0aGUgbG9uZ2l0dWRpbmFsIGZpZWxkIHN1cnZleSBkb3duc3RyZWFtIGF0IGEgcG9vbCBvdXRsZXQgLyByaWZmbGUgY3Jlc3QsIHRoaXMgaXMgbm90IGFsd2F5cyBwb3NzaWJsZS4gVGhpcyBjb2RlIGNyZWF0ZXMgYXJ0aWZpY2lhbCBkb3duc3RyZWFtIG5pY2sgcG9pbnRzIHRoYXQgd2lsbCBhbGxvdyB1cyB0byBpbmNsdWRlIGFyZWFzIG9mIHBvb2wgYXQgdGhlIGJvdHRvbSBvZiBvdXIgcmVhY2hlcyB0aGF0IHdlcmUgbm90IGNvbnRhaW5lZCBieSBhbiBvdXRsZXQuDQoNCiMgSWRlbnRpZnkgdW5pcXVlIHNpdGVzIGFuZCB5ZWFycyBpbiB0aGUgZGF0YQ0KdW5pcXVlX3NpdGVzX3llYXJzIDwtIHVuaXF1ZShkZlssIGMoIlNpdGUiLCAieWVhciIpXSkNCg0KIyBJbml0aWFsaXplIGFuIGVtcHR5IGxpc3QgdG8gc3RvcmUgYXJ0aWZpY2lhbCByb3dzDQphcnRpZmljaWFsX3Jvd3MgPC0gbGlzdCgpDQoNCiMgTG9vcCB0aHJvdWdoIGVhY2ggdW5pcXVlIGNvbWJpbmF0aW9uIG9mIFNpdGUgYW5kIHllYXINCmZvciAoaSBpbiAxOm5yb3codW5pcXVlX3NpdGVzX3llYXJzKSkgew0KICBzaXRlIDwtIHVuaXF1ZV9zaXRlc195ZWFycyRTaXRlW2ldDQogIHllYXIgPC0gdW5pcXVlX3NpdGVzX3llYXJzJHllYXJbaV0NCiAgDQogICMgU3Vic2V0IHRoZSBkYXRhIGZvciB0aGUgY3VycmVudCBzaXRlIGFuZCB5ZWFyDQogIHNpdGVfeWVhcl9kYXRhIDwtIHN1YnNldChkZiwgU2l0ZSA9PSBzaXRlICYgeWVhciA9PSB5ZWFyKQ0KICANCiAgIyBDYWxjdWxhdGUgbWVhbiBhbmQgc3RhbmRhcmQgZGV2aWF0aW9uIG9mIFRoYWx3ZWdfRGVwdGhfbSBmb3IgdGhlIGN1cnJlbnQgc3Vic2V0DQogIHRoYWx3ZWdfbWVhbiA8LSBtZWFuKHNpdGVfeWVhcl9kYXRhJFRoYWx3ZWdfRGVwdGhfbSwgbmEucm0gPSBUUlVFKQ0KICB0aGFsd2VnX3NkIDwtIHNkKHNpdGVfeWVhcl9kYXRhJFRoYWx3ZWdfRGVwdGhfbSwgbmEucm0gPSBUUlVFKQ0KICANCiMgUmV0cmlldmUgdGhlIGNvcnJlY3Qgc3BhY2luZyB2YWx1ZSBmcm9tIGNvbnN0YW50c19kZiBmb3IgdGhpcyBzaXRlIGFuZCB5ZWFyDQpzcGFjaW5nX3ZhbHVlIDwtIGNvbnN0YW50c19kZiAlPiUNCiAgZmlsdGVyKFNpdGUgPT0gc2l0ZSAmIHllYXIgPT0geWVhcikgJT4lDQogIGRpc3RpbmN0KHNwYWNpbmcpICU+JSAgIyBFbnN1cmUgdW5pcXVlIHNwYWNpbmcgdmFsdWVzDQogIHB1bGwoc3BhY2luZykgICMgRXh0cmFjdCB0aGUgc3BhY2luZyB2YWx1ZSBmb3IgdGhlIGN1cnJlbnQgc2l0ZS15ZWFyIGNvbWJpbmF0aW9uDQoNCiMgQ2hlY2sgaWYgdGhlIHNwYWNpbmcgdmFsdWUgaXMgdmFsaWQgKGxlbmd0aCBzaG91bGQgYmUgZXhhY3RseSAxKS4gVGhpcyBpcyBoZXJlIGJlY2F1c2Ugd2UgZW5jb3VudGVyZWQgaXNzdWVzIHdpdGggZHVwbGljYXRlczsgcmV0YWluaW5nIGl0IGluIGNhc2UgeW91IHJ1biBpbnRvIGEgc2ltaWxhciBlcnJvcg0KaWYgKGxlbmd0aChzcGFjaW5nX3ZhbHVlKSAhPSAxKSB7DQogIHN0b3AocGFzdGUoIlRoZXJlIGlzIGFuIGlzc3VlIHdpdGggdGhlIHNwYWNpbmcgdmFsdWUgZm9yIFNpdGU6Iiwgc2l0ZSwgImFuZCBZZWFyOiIsIHllYXIsIA0KICAgICAgICAgICAgICItIGV4cGVjdGVkIG9uZSB2YWx1ZSBidXQgZm91bmQiLCBsZW5ndGgoc3BhY2luZ192YWx1ZSksICJ2YWx1ZXMiKSkNCn0NCiAgIyBDcmVhdGUgYSBuZXcgcm93IHdpdGggTkEgdmFsdWVzIGZvciBhbGwgY29sdW1ucw0KICBuZXdfcm93IDwtIHNpdGVfeWVhcl9kYXRhWzEsIF0gICMgVXNlIHRoZSBmaXJzdCByb3cgYXMgYSB0ZW1wbGF0ZQ0KICBuZXdfcm93W10gPC0gTkEgICMgUmVwbGFjZSBhbGwgdmFsdWVzIHdpdGggTkENCiAgDQogICMgUHJvdmlkZSB2YWx1ZXMgZm9yIHRoZSBuaWNrIHBvaW50IG5ldyByb3csIG9ubHkgd2hlcmUgdmFsdWVzIGFyZSBuZWVkZWQNCiAgbmV3X3JvdyRMb2NhdGlvbl9Db2RlIDwtICJuaWNrcHRzIg0KICBuZXdfcm93JFRoYWx3ZWdfRGVwdGhfbSA8LSB0aGFsd2VnX21lYW4gLSB0aGFsd2VnX3NkDQogIG5ld19yb3ckZGlzdGFuY2UgPC0gLTEgKiBzcGFjaW5nX3ZhbHVlICAjIFVzZSB0aGUgc3BhY2luZyB2YWx1ZSBmb3IgZGlzdGFuY2UsIGFzc2lnbiBpdCBuZWdhdGl2ZSB0byBsYXRlciBmaWx0ZXIgb3V0DQogIG5ld19yb3ckRmluZXMgPC0gIk4iICAjIERlZmluZSB0aGVzZSByb3dzIHRvIHBsb3QgdGhlbSBwcm9wZXJseSBsYXRlcg0KICBuZXdfcm93JGZsb2F0dmVnIDwtIDAgDQogIG5ld19yb3ckc3VidmVnIDwtIDANCiAgbmV3X3JvdyRlbWVyZ3ZlZyA8LSAwDQogIG5ld19yb3ckU2l0ZSA8LSBzaXRlDQogIG5ld19yb3ckeWVhciA8LSB5ZWFyICANCiAgDQogICMgQWRkIHRoZSBuZXcgcm93IHRvIHRoZSBsaXN0IG9mIGFydGlmaWNpYWwgcm93cw0KICBhcnRpZmljaWFsX3Jvd3NbW2ldXSA8LSBuZXdfcm93DQp9DQoNCiMgQ29tYmluZSBhbGwgYXJ0aWZpY2lhbCByb3dzIGFuZCB0aGUgb3JpZ2luYWwgZGF0YQ0KZGZfYXJ0aWZpY2lhbCA8LSBkby5jYWxsKHJiaW5kLCBhcnRpZmljaWFsX3Jvd3MpDQpkZiA8LSByYmluZChkZl9hcnRpZmljaWFsLCBkZikNCmBgYA0KVGhlIHJlc2lkdWFsIHN1cmZhY2UgaXMgdGhlIHdhdGVyIHN1cmZhY2UgYXQgdGhlIHBvaW50IHdoZW4gc3RyZWFtZmxvdyBhcHByb2FjaGVzIHplcm8sIGFuZCByZXNpZHVhbCBkZXB0aCBpcyB0aGUgdmVydGljYWwgZGlzdGFuY2UgYmV0d2VlbiB0aGUgcmVzaWR1YWwgc3VyZmFjZSBhbmQgdGhlIHN0cmVhbSBiZWQuIEFzIHN1Y2gsIHdoZW4gd2UgZXN0aW1hdGUgcmVzaWR1YWwgcG9vbHMgYW5kIHJlc2lkdWFsIGRlcHRocywgdGhlc2UgYXJlIGZlYXR1cmVzIHRoYXQgYXJlIGluZGVwZW5kZW50IG9mIGZsb3cgY29uZGl0aW9ucyBhdCB0aGUgdGltZSBvZiB0aGUgZmllbGQgc3VydmV5LiBXaGlsZSB0aGV5IG1pZ2h0IGJlIHJlcHJlc2VudGF0aXZlIG9mIGFjdHVhbCBwb29sIGNvbmRpdGlvbnMgZHVyaW5nIHRpbWVzIG9mIHZlcnkgbG93IGZsb3csIHRoZWlyIHZhbHVlIGxpZXMgd2l0aCB0aGUgYWJpbGl0eSB0byBtYWtlIGNvbXBhcmlzb25zIG9mIHBvb2wgaGFiaXRhdCBhbW9uZyB5ZWFycyBhbmQvb3IgcmVhY2hlcyB3aXRob3V0IHF1YW50aWZ5aW5nIGFuZCBjb250cm9sbGluZyBmb3IgdmFyaWFibGUgZmxvdyBjb25kaXRpb25zLiANCg0KT3VyIGNvZGUgdXNlcyB0aGUgc2VxdWVuY2Ugb2YgdGhhbHdlZyBkZXB0aCBtZWFzdXJlbWVudHMgdG8gaWRlbnRpZnkgcG90ZW50aWFsIHBvb2wgb3V0bGV0cyBpbiB0aGUgc2FtcGxlZCByZWFjaCwgYW5kIGVzdGltYXRlcyByZXNpZHVhbCBkZXB0aHMgYXQgZWFjaCBtZWFzdXJlbWVudCBsb2NhdGlvbiBiYXNlZCBvbiBhIHByb2plY3RlZCByZXNpZHVhbCBzdXJmYWNlIHRoYXQgZXh0ZW5kcyB1cHN0cmVhbSBmcm9tIGVhY2ggcG9vbCBvdXRsZXQuIFRoZSByZXNpZHVhbCBzdXJmYWNlIGlzIHByb2plY3RlZCB1c2luZyB0aGUgZXhwZWN0ZWQgcG9vbCB3YXRlciBzdXJmYWNlIHNsb3BlICh3aGljaCBpcyBlc3RpbWF0ZWQgdXNpbmcgU3RhY2sncyBlbXBpcmljYWwgZXF1YXRpb24sIGluY29ycG9yYXRpbmcgdGhlIGF2ZXJhZ2UgcmVhY2ggc2xvcGUgdGhhdCB5b3UgZW50ZXJlZCBhcyBhIGNvbnN0YW50KS4gDQoNCkl0IGlzIGltcG9ydGFudCB0byBub3RlIHRoYXQgd2hlbiB3ZSBpZGVudGlmeSBwb29sIG91dGxldHMgb3IgcmlmZmxlIGNyZXN0cyAoZWl0aGVyIGluIHRoZSBmaWVsZCBvciB1c2luZyB0aGlzIGNvZGUpLCB3ZSB1c3VhbGx5IGJhc2UgdGhpcyBkZXRlcm1pbmF0aW9uIG9uIHRoZSBiZWQgZWxldmF0aW9uIGFuZC9vciB3YXRlciBkZXB0aCBhdCB0aGUgY3VycmVudCBsb2NhdGlvbiBjb21wYXJlZCB3aXRoIHRoZSBhcmVhcyBpbW1lZGlhdGVseSBhZGphY2VudC4gSG93ZXZlciwgYSBwb3RlbnRpYWwgcG9vbCBvdXRsZXQgd2lsbCBub3QgJ2JlaGF2ZScgYXMgYSBwb29sIG91dGxldCB1bmRlciBhbGwgZmxvdyBjb25kaXRpb25zOiBpdCBjb3VsZCBiZSBoaWdoIGFuZCBkcnkgdW5kZXIgdmVyeSBsb3cgZmxvdyBjb25kaXRpb25zLCBvciBpdCBjb3VsZCBpdHNlbGYgYmUgd2l0aGluIGEgcG9vbCBkdWUgdG8gdGhlIGJhY2t3YXRlcmluZyBlZmZlY3RzIG9mIGEgaGlnaGVyLWVsZXZhdGlvbiBwb29sIG91dGxldCBkb3duc3RyZWFtLiBGcm9tIGhlcmUgb253YXJkLCB3ZSB3aWxsIHVzZSB0aGUgdGVybSAqJ2xvY2FsIGRlcHRoIG1pbmltYScqICgnTERNJyBpbiBjb2RlKSB0byByZWZlciB0byBsb2NhdGlvbnMgdGhhdCBoYXZlIHRoZSBwb3RlbnRpYWwgdG8gYmUgcG9vbCBvdXRsZXRzIC0gdGhhdCBpcywgdGhleSBhcmUgbGVzcyBkZWVwIHRoYW4gYXJlYXMgaW1tZWRpYXRlbHkgZG93bnN0cmVhbSBhbmQgdXBzdHJlYW0sIGFjY291bnRpbmcgZm9yIHRoZSBzbG9wZSBvZiB0aGUgc3RyZWFtLiBXZSB3aWxsIHJlc2VydmUgdGhlIHRlcm0gJ3Bvb2wgb3V0bGV0JyBmb3IgY2FzZXMgd2hlbiBsb2NhbCBkZXB0aCBtaW5pbWEgd291bGQgYmUgZXhwZWN0ZWQgdG8gYWN0dWFsbHkgYmFja3dhdGVyIGEgcG9vbCB1bmRlciBmbG93IGNvbmRpdGlvbnMgYXBwcm9hY2hpbmcgemVyby4gDQoNCkF0IHRoaXMgcG9pbnQgb3VyIGNvZGUgd2lsbCBnZW5lcmF0ZSBhIG5ldyBkYXRhZnJhbWUgKHJlc2lkdWFscy5kZikgd2l0aCB0aGUgbG9jYWwgZGVwdGggbWluaW1hIGlkZW50aWZpZWQgYW5kIHRoZSByZXNpZHVhbCBzdXJmYWNlIHByb2plY3RlZC4gSWYgeW91IGFyZSBpbnRlcmVzdGVkIGluIGhvdyB0aGlzIGlzIGRvbmUsIGNoZWNrIG91dCB0aGUgUiBjb2RlLiBGb3IgZXZlcnlvbmUgZWxzZSwgaGVyZSBhcmUgc29tZSBmaXNoOiANCg0K8J+Qn/CfkJ/wn5Cf8J+Qn/CfkJ8g8J+Qn/CfkJ/wn5Cf8J+Qn/CfkJ8g8J+Qn/CfkJ/wn5Cf8J+Qn/CfkJ8g8J+Qn/CfkJ/wn5Cf8J+Qn/CfkJ8g8J+Qn/CfkJ/wn5Cf8J+Qn/CfkJ8g8J+Qn/CfkJ/wn5Cf8J+Qn/CfkJ8g8J+Qn/CfkJ/wn5Cf8J+Qn/CfkJ8g8J+Qn/CfkJ/wn5Cf8J+Qn/CfkJ8g8J+Qn/CfkJ/wn5Cf8J+Qn/CfkJ8NCg0KYGBge3IgcmVzaWR1YWwgc3VyZmFjZXMgYW5kIGRlcHRocywgZWNobyA9IEZBTFNFfQ0KIyBOQjogd2UgaGF2ZSBtb2RpZmllZCB0aGUgYXBwcm9hY2ggdXNlZCBpbiBLYXVmbWFuIGV0IGFsLiAxOTk5IHRvIGFjY291bnQgZm9yIHRoZSBmYWN0IHRoYXQgd2UgbWVhc3VyZWQgdGhlIG1heGltdW0gZGVwdGggb2YgcG9vbHMNCiMgYW5kIHRoZSBkZXB0aCBvZiBwb29sIG91dGxldHMgKndoZXJldmVyIHdlIGVuY291bnRlcmVkIHRoZW0qIGFsb25nIG91ciBzYW1wbGVkIHJlYWNoIChub3QganVzdCBhdCBwcmVkZXRlcm1pbmVkIGludGVydmFscykuDQojIEFzIHN1Y2gsIHdlIGJhc2Ugb3VyIHJlc2lkdWFsIHBvb2wgY2FsY3VsYXRpb25zIG9uIGRpZmZlcmVuY2VzIGluIHRoZSBkaXN0YW5jZSBjb2x1bW4gdGhhdCB3ZSBwcmV2aW91c2x5IGNvbXB1dGVkLg0KDQojIE1lcmdlIGNvbnN0YW50c19kZiB3aXRoIGRmIHRvIGFkZCB0aGUgc2xvcGUgYW5kIHdldHdpZHRoIHZhbHVlcw0KZGYgPC0gZGYgJT4lDQogIGxlZnRfam9pbihjb25zdGFudHNfZGYsIGJ5ID0gYygiU2l0ZSIsICJ5ZWFyIikpDQoNCiMgUmVzaWR1YWwgZGVwdGggZnVuY3Rpb24gdG8gY3JlYXRlIHJlc2lkdWFscy5kZiAoaW5zdGVhZCBvZiBtb2RpZnlpbmcgZGYpDQpjYWxjdWxhdGVfcmVzaWR1YWxfZGVwdGhzIDwtIGZ1bmN0aW9uKGRmKSB7DQogICMgRW5zdXJlIHRoZSBkYXRhZnJhbWUgaXMgc29ydGVkIGJ5IGRpc3RhbmNlLCBzbyB0aGF0IGNhbGN1bGF0aW9ucyBwcm9ncmVzcyBpbiBjb3JyZWN0IG9yZGVyDQogIGRmIDwtIGRmW29yZGVyKGRmJGRpc3RhbmNlKSwgXQ0KICANCiAgIyBJbml0aWFsaXplIHJlcXVpcmVkIGNvbHVtbnMNCiAgcmVzaWR1YWxzLmRmIDwtIGRmICMgU3RhcnQgd2l0aCBhIGNvcHkgb2YgdGhlIGlucHV0IGRhdGFmcmFtZQ0KICByZXNpZHVhbHMuZGYkcmVzaWR1YWxfc3VyZmFjZSA8LSBOQQ0KICByZXNpZHVhbHMuZGYkcmVzaWR1YWxfZGVwdGggPC0gTkENCiAgcmVzaWR1YWxzLmRmJHJlc2lkdWFsX3dpZHRoIDwtIE5BDQogIHJlc2lkdWFscy5kZiRMRE1faWQgPC0gTkENCiAgDQogICMgRGVmaW5lIGNvbnN0YW50cyAoc2xvcGUgZmFjdG9yIGFkanVzdG1lbnQgZm9yIHBlcmNlbnRhZ2UuIEZvcm11bGEgZnJvbSBTdGFjayAxOTg5KQ0KICBzbG9wZV9mYWN0b3IgPC0gKDAuMTIgKyAwLjI1ICogcmVzaWR1YWxzLmRmJFNsb3BlWzFdKSAvIDEwMA0KICB3ZXR3aWR0aCA8LSByZXNpZHVhbHMuZGYkV2V0V2lkdGhbMV0NCiAgDQogICMgSWRlbnRpZnkgbG9jYWwgZGVwdGggbWluaW1hIChyaWZmbGUgY3Jlc3RzL2NvbnRyb2wgcG9pbnRzL3Bvb2wgb3V0bGV0cykNCiAgTERNX2lkIDwtIDAgDQogIGxhc3RfcmVzaWR1YWxfc3VyZmFjZSA8LSBOQQ0KICBsYXN0X3Jlc2lkdWFsX2luZGV4IDwtIDAuMQ0KICANCiAgIyBIYW5kbGUgYXJ0aWZpY2lhbCBvdXRsZXQgKG5lZ2F0aXZlIGRpc3RhbmNlIHZhbHVlKQ0KICBpZiAocmVzaWR1YWxzLmRmJGRpc3RhbmNlWzFdIDwgMCkgew0KICAgIExETV9pZCA8LSBMRE1faWQgKyAxDQogICAgZG93bnN0cmVhbV9kZXB0aCA8LSByZXNpZHVhbHMuZGYkVGhhbHdlZ19EZXB0aF9tWzFdDQogICAgZG93bnN0cmVhbV9pbmRleCA8LSAxDQogICAgcmVzaWR1YWxzLmRmJExETV9pZFsxXSA8LSBMRE1faWQNCiAgICANCiAgICAjIFByb2plY3QgcmVzaWR1YWwgc3VyZmFjZSB1cHN0cmVhbSBmcm9tIHRoZSBhcnRpZmljaWFsIG91dGxldA0KICAgIGZvciAoZSBpbiAxOm5yb3cocmVzaWR1YWxzLmRmKSkgew0KICAgICAgc3BhY2luZ19jdXJyZW50IDwtIHJlc2lkdWFscy5kZiRkaXN0YW5jZVtlXSAtIHJlc2lkdWFscy5kZiRkaXN0YW5jZVsxXQ0KICAgICAgcmVzaWR1YWxfc3VyZmFjZSA8LSBkb3duc3RyZWFtX2RlcHRoICsgc2xvcGVfZmFjdG9yICogc3BhY2luZ19jdXJyZW50DQoNCiAgICAgIGlmICghaXMubmEocmVzaWR1YWxzLmRmJFRoYWx3ZWdfRGVwdGhfbVtlXSkpIHsNCiAgICAgICAgaWYgKHJlc2lkdWFsX3N1cmZhY2UgPD0gcmVzaWR1YWxzLmRmJFRoYWx3ZWdfRGVwdGhfbVtlXSkgew0KICAgICAgICAgIHJlc2lkdWFscy5kZiRyZXNpZHVhbF9zdXJmYWNlW2VdIDwtIHJlc2lkdWFsX3N1cmZhY2UNCiAgICAgICAgICByZXNpZHVhbHMuZGYkcmVzaWR1YWxfZGVwdGhbZV0gPC0gcmVzaWR1YWxzLmRmJFRoYWx3ZWdfRGVwdGhfbVtlXSAtIHJlc2lkdWFsX3N1cmZhY2UNCiAgICAgICAgfSBlbHNlIHsNCiAgICAgICAgICByZXNpZHVhbHMuZGYkcmVzaWR1YWxfc3VyZmFjZVtlXSA8LSByZXNpZHVhbHMuZGYkVGhhbHdlZ19EZXB0aF9tW2VdDQogICAgICAgICAgcmVzaWR1YWxzLmRmJHJlc2lkdWFsX2RlcHRoW2VdIDwtIDANCiAgICAgICAgICBicmVhaw0KICAgICAgICB9DQogICAgICB9IGVsc2Ugew0KICAgICAgICBicmVhaw0KICAgICAgfQ0KICAgIH0NCiAgfQ0KDQogICMgSXRlcmF0ZSB0aHJvdWdoIHRoZSByZXN0IG9mIHRoZSByb3dzIHRvIGlkZW50aWZ5IGxvY2FsIGRlcHRoIG1pbmltYQ0KICBmb3IgKGIgaW4gMjoobnJvdyhyZXNpZHVhbHMuZGYpIC0gMSkpIHsNCiAgICBzcGFjaW5nX3ByZXYgPC0gcmVzaWR1YWxzLmRmJGRpc3RhbmNlW2JdIC0gcmVzaWR1YWxzLmRmJGRpc3RhbmNlW2IgLSAxXQ0KICAgIHNwYWNpbmdfbmV4dCA8LSByZXNpZHVhbHMuZGYkZGlzdGFuY2VbYiArIDFdIC0gcmVzaWR1YWxzLmRmJGRpc3RhbmNlW2JdDQogICAgDQogICAgIyBDaGVjayBpZiB0aGUgY3VycmVudCBwb2ludCBpcyBhIGxvY2FsIGRlcHRoIG1pbmltdW0NCiAgICBpZiAoKHJlc2lkdWFscy5kZiRUaGFsd2VnX0RlcHRoX21bYl0gPD0gKHJlc2lkdWFscy5kZiRUaGFsd2VnX0RlcHRoX21bYiAtIDFdICsgc2xvcGVfZmFjdG9yICogc3BhY2luZ19wcmV2KSAmJg0KICAgICAgICAgKHJlc2lkdWFscy5kZiRUaGFsd2VnX0RlcHRoX21bYl0gKyBzbG9wZV9mYWN0b3IgKiBzcGFjaW5nX25leHQpIDwgcmVzaWR1YWxzLmRmJFRoYWx3ZWdfRGVwdGhfbVtiICsgMV0pIHx8DQogICAgICAgIHJlc2lkdWFscy5kZiRkaXN0YW5jZVtiXSA8IDApIHsNCiAgICAgIA0KICAgICAgTERNX2lkIDwtIExETV9pZCArIDENCiAgICAgIGRvd25zdHJlYW1fZGVwdGggPC0gcmVzaWR1YWxzLmRmJFRoYWx3ZWdfRGVwdGhfbVtiXQ0KICAgICAgZG93bnN0cmVhbV9pbmRleCA8LSBiDQogICAgICByZXNpZHVhbHMuZGYkTERNX2lkW2JdIDwtIExETV9pZA0KDQogICAgICBpZiAoaXMubmEobGFzdF9yZXNpZHVhbF9zdXJmYWNlKSB8fCByZXNpZHVhbHMuZGYkZGlzdGFuY2VbYl0gPiByZXNpZHVhbHMuZGYkZGlzdGFuY2VbbGFzdF9yZXNpZHVhbF9pbmRleF0pIHsNCiAgICAgICAgaWYgKGlzLm5hKGxhc3RfcmVzaWR1YWxfc3VyZmFjZSkpIHsNCiAgICAgICAgICBwcm9qZWN0ZWRfcmVzaWR1YWxfc3VyZmFjZSA8LSByZXNpZHVhbHMuZGYkcmVzaWR1YWxfc3VyZmFjZVtiIC0gMV0gKyBzbG9wZV9mYWN0b3IgKiAocmVzaWR1YWxzLmRmJGRpc3RhbmNlW2JdIC0gcmVzaWR1YWxzLmRmJGRpc3RhbmNlW2IgLSAxXSkNCiAgICAgICAgfSBlbHNlIHsNCiAgICAgICAgICBwcm9qZWN0ZWRfcmVzaWR1YWxfc3VyZmFjZSA8LSBsYXN0X3Jlc2lkdWFsX3N1cmZhY2UgKyBzbG9wZV9mYWN0b3IgKiAocmVzaWR1YWxzLmRmJGRpc3RhbmNlW2JdIC0gcmVzaWR1YWxzLmRmJGRpc3RhbmNlW2xhc3RfcmVzaWR1YWxfaW5kZXhdKQ0KICAgICAgICB9DQoNCiAgICAgICAgaWYgKGRvd25zdHJlYW1fZGVwdGggPD0gcHJvamVjdGVkX3Jlc2lkdWFsX3N1cmZhY2UpIHsNCiAgICAgICAgICBsYXN0X3Jlc2lkdWFsX3N1cmZhY2UgPC0gZG93bnN0cmVhbV9kZXB0aA0KICAgICAgICAgIGxhc3RfcmVzaWR1YWxfaW5kZXggPC0gYg0KICAgICAgICB9IGVsc2Ugew0KICAgICAgICAgIG5leHQNCiAgICAgICAgfQ0KICAgICAgfQ0KICAgICAgDQogICAgICBmb3IgKGUgaW4gKGxhc3RfcmVzaWR1YWxfaW5kZXggKyAxKTpucm93KHJlc2lkdWFscy5kZikpIHsNCiAgICAgICAgc3BhY2luZ19jdXJyZW50IDwtIHJlc2lkdWFscy5kZiRkaXN0YW5jZVtlXSAtIHJlc2lkdWFscy5kZiRkaXN0YW5jZVtsYXN0X3Jlc2lkdWFsX2luZGV4XQ0KICAgICAgICByZXNpZHVhbF9zdXJmYWNlIDwtIGxhc3RfcmVzaWR1YWxfc3VyZmFjZSArIHNsb3BlX2ZhY3RvciAqIHNwYWNpbmdfY3VycmVudA0KDQogICAgICAgIGlmICghaXMubmEocmVzaWR1YWxzLmRmJFRoYWx3ZWdfRGVwdGhfbVtlXSkgJiYgIWlzLm5hKHJlc2lkdWFsX3N1cmZhY2UpKSB7DQogICAgICAgICAgaWYgKHJlc2lkdWFsX3N1cmZhY2UgPiByZXNpZHVhbHMuZGYkVGhhbHdlZ19EZXB0aF9tW2VdKSB7DQogICAgICAgICAgICByZXNpZHVhbHMuZGYkcmVzaWR1YWxfc3VyZmFjZVtlXSA8LSByZXNpZHVhbHMuZGYkVGhhbHdlZ19EZXB0aF9tW2VdDQogICAgICAgICAgICByZXNpZHVhbHMuZGYkcmVzaWR1YWxfZGVwdGhbZV0gPC0gMA0KICAgICAgICAgICAgbGFzdF9yZXNpZHVhbF9zdXJmYWNlIDwtIHJlc2lkdWFscy5kZiRUaGFsd2VnX0RlcHRoX21bZV0NCiAgICAgICAgICAgIGxhc3RfcmVzaWR1YWxfaW5kZXggPC0gZQ0KICAgICAgICAgICAgYnJlYWsNCiAgICAgICAgICB9IGVsc2Ugew0KICAgICAgICAgICAgcmVzaWR1YWxzLmRmJHJlc2lkdWFsX3N1cmZhY2VbZV0gPC0gcmVzaWR1YWxfc3VyZmFjZQ0KICAgICAgICAgICAgcmVzaWR1YWxfZGVwdGggPC0gcmVzaWR1YWxzLmRmJFRoYWx3ZWdfRGVwdGhfbVtlXSAtIHJlc2lkdWFsX3N1cmZhY2UNCiAgICAgICAgICAgIHJlc2lkdWFscy5kZiRyZXNpZHVhbF9kZXB0aFtlXSA8LSBpZmVsc2UocmVzaWR1YWxfZGVwdGggPiAwLCByZXNpZHVhbF9kZXB0aCwgMCkNCiAgICAgICAgICAgIGxhc3RfcmVzaWR1YWxfc3VyZmFjZSA8LSByZXNpZHVhbF9zdXJmYWNlDQogICAgICAgICAgICBsYXN0X3Jlc2lkdWFsX2luZGV4IDwtIGUNCiAgICAgICAgICB9DQogICAgICAgIH0NCiAgICAgIH0NCiAgICB9DQogIH0NCiAgDQojIHRoaXMgYml0IGVzdGltYXRlcyB0aGUgd2lkdGggb2YgdGhlIGNoYW5uZWwgd2hlbiBmbG93IGFwcHJvYWNoZXMgemVybyAodGhlIHJlc2lkdWFsIHdpZHRoKSBieSB1c2luZyB0aGUgcmF0aW8gb2YgcmVzaWR1YWwgZGVwdGhzIHRvIG9ic2VydmVkIGRlcHRocw0KICByZXNpZHVhbHMuZGYkcmVzaWR1YWxfd2lkdGggPC0gaWZlbHNlKA0KICAgIGlzLm5hKHJlc2lkdWFscy5kZiRyZXNpZHVhbF9kZXB0aCkgfCBpcy5uYShyZXNpZHVhbHMuZGYkVGhhbHdlZ19EZXB0aF9tKSB8IHJlc2lkdWFscy5kZiRUaGFsd2VnX0RlcHRoX20gPT0gMCwNCiAgICBOQSwNCiAgICB3ZXR3aWR0aCAqIChyZXNpZHVhbHMuZGYkcmVzaWR1YWxfZGVwdGggLyByZXNpZHVhbHMuZGYkVGhhbHdlZ19EZXB0aF9tKQ0KICApDQogIA0KICByZXR1cm4ocmVzaWR1YWxzLmRmKQ0KfQ0KDQojIE5vdyB3ZSB3aWxsIGFwcGx5IHRoaXMgZnVuY3Rpb24gYWNyb3NzIGFsbCBzaXRlcyBhbmQgeWVhcnMNCiMgR3JvdXAgYnkgU2l0ZSBhbmQgWWVhciwgYW5kIGFwcGx5IHRoZSBjYWxjdWxhdGVfcmVzaWR1YWxfZGVwdGhzIGZ1bmN0aW9uDQpyZXNpZHVhbHMuZGYgPC0gZGYgJT4lDQogIGdyb3VwX2J5KFNpdGUsIHllYXIpICU+JQ0KICBkbyhjYWxjdWxhdGVfcmVzaWR1YWxfZGVwdGhzKC4pKSAlPiUNCiAgdW5ncm91cCgpDQpgYGANCg0KQmVsb3cgd2UgZ2VuZXJhdGUgYSBxdWljayB2aXN1YWwgb2YgdGhlIGRlcHRocyBhbmQgcmVzaWR1YWwgc3VyZmFjZXMgdGhhdCB3ZXJlIHByb2plY3RlZCBieSB0aGUgY29kZS4gVGFrZSBhIGxvb2sgdG8gZW5zdXJlIGl0IG1hdGNoZXMgeW91ciB1bmRlcnN0YW5kaW5nIG9mIHJlc2lkdWFsIHBvb2xzIGFuZCBsb29rIGZvciBwb3RlbnRpYWwgZXJyb3JzICh0aGUgZmlndXJlIGlzIGludGVyYWN0aXZlLCBzbyB6b29tIGluIGlmIHlvdSBoYXZlIHNldmVyYWwgcGxvdHMpLiBUcnkgdG8gaWRlbnRpZnkgc29tZSBsb2NhbCBkZXB0aCBtaW5pbWEgdGhhdCBhcmUgd2l0aGluIGEgcG9vbCAoaWYgcHJlc2VudCBpbiB5b3VyIGRhdGEpLCBhbmQgY29tcGFyZSB0aGVzZSB0byB0aGUgbG9jYWwgZGVwdGggbWluaW1hIHRoYXQgYWN0IGFzIHBvb2wgb3V0bGV0cyAtIHRoZSBzaGFsbG93ZXIgZmVhdHVyZXMgYXQgd2hpY2ggcmVzaWR1YWwgc3VyZmFjZXMgYmVnaW4uIFJlbWVtYmVyIHRoYXQgdGhlIHJlc2lkdWFsIHN1cmZhY2Ugc2xvcGVzIGRvd24gaW4gdGhlc2UgZmlndXJlcyBhcyB5b3UgcHJvZ3Jlc3MgdXBzdHJlYW0gKHJpZ2h0IGluIHRoZSBwbG90cyksIHdoaWNoIGlzIHRvIGNvbXBlbnNhdGUgZm9yIHRoZSBmYWN0IHRoYXQgdGhlIHRydWUgdGhhbHdlZyBzdXJmYWNlIHNsb3BlcyBkb3duIGFzIHlvdSBwcm9ncmVzcyBkb3duc3RyZWFtLg0KDQpgYGB7ciB2aXN1YWxpc2UgcmVzaWR1YWwgc3VyZmFjZXMsIGVjaG8gPSBGQUxTRX0NCiMgRW5zdXJlICd5ZWFyJyBpcyBvcmRlcmVkIGZyb20gb2xkZXN0IHRvIHlvdW5nZXN0DQpyZXNpZHVhbHMuZGYkeWVhciA8LSBmYWN0b3IocmVzaWR1YWxzLmRmJHllYXIsIGxldmVscyA9IHNvcnQodW5pcXVlKHJlc2lkdWFscy5kZiR5ZWFyKSwgZGVjcmVhc2luZyA9IEZBTFNFKSkNCg0KZ2c8LSBnZ3Bsb3QocmVzaWR1YWxzLmRmLCBhZXMoeCA9IGRpc3RhbmNlKSkgKw0KICAjIFBsb3QgVGhhbHdlZyBEZXB0aCBhcyBhIGxpbmUNCiAgZ2VvbV9saW5lKGFlcyh5ID0gLVRoYWx3ZWdfRGVwdGhfbSksIGNvbG9yID0gImJsYWNrIiwgbGluZXdpZHRoID0gMSwgbGluZXR5cGUgPSAic29saWQiKSArDQogIA0KICAjIFBsb3QgUmVzaWR1YWwgU3VyZmFjZSBhcyBwb2ludHMgKGluc3RlYWQgb2YgbGluZSwgd2hpY2ggd291bGQgJ2p1bXAnIHVwIGF0IHVwc3RyZWFtIG9mIHNvbWUgcG9vbHMpDQogIGdlb21fcG9pbnQoYWVzKHkgPSAtcmVzaWR1YWxfc3VyZmFjZSksIGNvbG9yID0gImJsdWUiLCBzaXplID0gMSkgKw0KICANCiAgIyBBZGQgbGFiZWxzIGFuZCB0aXRsZQ0KICBsYWJzKHggPSAiRGlzdGFuY2UgKG0pIiwgeSA9ICJEZXB0aCAobSkiLCB0aXRsZSA9ICJUaGFsd2VnIERlcHRoIGFuZCBSZXNpZHVhbCBTdXJmYWNlIikgKw0KICANCiAgIyBGbGlwIHRoZSB5LWF4aXMgdG8gbWF0Y2ggdGhlIGludmVydGVkIGxpbmVzDQogICBzY2FsZV95X2NvbnRpbnVvdXMoDQogICAgbmFtZSA9ICJEZXB0aCAobSkiLCANCiAgICBicmVha3MgPSBzZXEoLW1heChyZXNpZHVhbHMuZGYkVGhhbHdlZ19EZXB0aF9tLCBuYS5ybSA9IFRSVUUpLCAwLCBieSA9IDAuMiksICANCiAgICBsYWJlbHMgPSBzY2FsZXM6Om51bWJlcl9mb3JtYXQoYWNjdXJhY3kgPSAwLjIsIGJpZy5tYXJrID0gIiIsIGRlY2ltYWwubWFyayA9ICIuIikoDQogICAgICBhYnMoc2VxKC1tYXgocmVzaWR1YWxzLmRmJFRoYWx3ZWdfRGVwdGhfbSwgbmEucm0gPSBUUlVFKSwgMCwgYnkgPSAwLjIpKQ0KICAgICkgICMgQ29udmVydCB0byBwb3NpdGl2ZSBmb3IgbGFiZWxzIGFuZCBlbnN1cmUgYWNjdXJhY3kgb2YgMiBkZWNpbWFscw0KICApICsNCiAgDQogICMgQ3VzdG9taXplIHRoZW1lDQogIHRoZW1lX21pbmltYWwoKSArDQogIHRoZW1lKA0KICAgIGF4aXMudGV4dC55ID0gZWxlbWVudF90ZXh0KGNvbG9yID0gImJsYWNrIiksDQogICAgYXhpcy50aXRsZS55ID0gZWxlbWVudF90ZXh0KGNvbG9yID0gImJsYWNrIiksDQogICAgcGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChoanVzdCA9IDAuNSksDQogICAgc3RyaXAudGV4dCA9IGVsZW1lbnRfdGV4dChzaXplID0gOCwgZmFjZSA9ICJib2xkIikNCiAgKSArDQogIA0KICAjIFVzZSBmYWNldF9ncmlkIHRvIGFycmFuZ2UgYnkgU2l0ZSAocm93cykgYW5kIFllYXIgKGNvbHVtbnMpDQogIGZhY2V0X2dyaWQoU2l0ZSB+IHllYXIsIHNjYWxlcyA9ICJmaXhlZCIpICsgICMgUm93cyA9IFNpdGUsIENvbHVtbnMgPSBZZWFyIChvbGRlc3Qgb24gbGVmdCkNCiAgDQogICMgQ3VzdG9taXplIGdyaWQgc3BhY2luZyBpZiBuZWNlc3NhcnkNCiAgdGhlbWUoDQogICAgc3RyaXAudGV4dC55ID0gZWxlbWVudF90ZXh0KGFuZ2xlID05MCksICANCiAgICBwYW5lbC5zcGFjaW5nID0gdW5pdCgxLCAibGluZXMiKSAgIyBBZGp1c3Qgc3BhY2UgYmV0d2VlbiBwYW5lbHMNCiAgKQ0KaW50ZXJhY3RpdmVfcGxvdCA8LSBnZ3Bsb3RseShnZykNCmludGVyYWN0aXZlX3Bsb3QNCg0KIyBFeHBvcnQgYSBmaWd1cmUgKGNvbW1lbnRlZCBvdXQgaW4gZmF2b3VyIG9mIGJlbG93IGZpZ3VyZSkNCiMgZXhwb3J0X3Bsb3QoZ2csICJUaGFsd2VnIFdhdGVyIERlcHRoIGFuZCBSZXNpZHVhbCBTdXJmYWNlLnBkZiIpDQojIGV4cG9ydF9wbG90KGludGVyYWN0aXZlX3Bsb3QsICJUaGFsd2VnIFdhdGVyIERlcHRoIGFuZCBSZXNpZHVhbCBTdXJmYWNlLmh0bWwiKQ0KYGBgDQoNCiMgJ01lYW5pbmdmdWwnIFBvb2xzDQoNCkNvbnNpZGVyIHRoZSB2ZXJ0aWNhbCBleGFnZ2VyYXRpb24gb2YgdGhlIGFib3ZlIGZpZ3VyZSAtIHNvbWUgJ3Bvb2xzJyBtYXkgYmUgdmVyeSBzaGFsbG93IGluZGVlZCwgYW5kIG1pZ2h0IG5vdCBuZWNlc3NhcmlseSBjb3JyZXNwb25kIHdpdGggd2hhdCB5b3Ugd291bGQgYWN0dWFsbHkgY29uc2lkZXIgYSBwb29sIGluIGEgc3RyZWFtLiANCg0KSXQgaXMgcHJvYmFibHkgbW9zdCBpbmZvcm1hdGl2ZSB0byBjb25zaWRlciBtZXRyaWNzIHJlbGF0aW5nIG9ubHkgdG8gdGhvc2UgcG9vbHMgdGhhdCBhcmUgZXhwZWN0ZWQgdG8gYmUgaHlkcmF1bGljYWxseSBhbmQvb3IgYmlvbG9naWNhbGx5IG1lYW5pbmdmdWwuIFRoZSBjb2RlIG5vdyBkZXRlY3RzIHBvb2xzIGFuZCBhc3NpZ25zIGVhY2ggYSBwb29sIElELCBzbyB0aGF0IHdlIGNhbiBjaGFyYWN0ZXJpc2UgdGhlbSBpbmRpdmlkdWFsbHkgYW5kIHNlbGVjdCBzdWJzZXRzIGFzIGFwcHJvcHJpYXRlLg0KDQpgYGB7ciBJRCBhY3R1YWwgcG9vbHMsIGVjaG8gPSBGQUxTRX0NCmlkZW50aWZ5X3Jlc2lkdWFsX3Bvb2xzIDwtIGZ1bmN0aW9uKGRmKSB7DQogICMgSW5pdGlhbGl6ZSB0aGUgcG9vbCBJRCBjb2x1bW4NCiAgZGYkcG9vbF9pZCA8LSBhcy5jaGFyYWN0ZXIoTkEpICAjIERlZmF1bHQgaXMgTkEgKG5vdCBpbiBhIHBvb2wpDQogIA0KICAjIFZhcmlhYmxlcyB0byB0cmFjayBwb29sIHN0YXR1cw0KICBwb29sX2lkIDwtIDANCiAgaW5fcG9vbCA8LSBGQUxTRSAgIyBXaGV0aGVyIHdlIGFyZSBjdXJyZW50bHkgaW5zaWRlIGEgcG9vbA0KICANCiAgIyBJdGVyYXRlIHRocm91Z2ggcm93cyB0byBpZGVudGlmeSBwb29scw0KICBmb3IgKGkgaW4gMTpucm93KGRmKSkgew0KICAgICMgQ2hlY2sgaWYgdGhlIGN1cnJlbnQgcm93IHN0YXJ0cyBhIG5ldyBwb29sDQogICAgaWYgKCFpbl9wb29sICYmICFpcy5uYShkZiRMRE1faWRbaV0pKSB7DQogICAgICBwb29sX2lkIDwtIHBvb2xfaWQgKyAxICAjIEluY3JlbWVudCBwb29sIElEDQogICAgICBpbl9wb29sIDwtIFRSVUUgICMgRW50ZXIgYSBwb29sDQogICAgICBkZiRwb29sX2lkW2ldIDwtIHBvb2xfaWQgICMgQXNzaWduIHRoZSBuZXcgcG9vbCBJRCB0byB0aGlzIHJvdw0KICAgICAgbmV4dCAgIyBTa2lwIHRvIHRoZSBuZXh0IGl0ZXJhdGlvbiB0byBhdm9pZCBmdXJ0aGVyIGxvZ2ljIGZvciB0aGlzIHJvdw0KICAgIH0NCiAgICANCiAgICAjIElmIGFscmVhZHkgaW4gYSBwb29sLCBhc3NpZ24gdGhlIHBvb2wgSUQNCiAgICBpZiAoaW5fcG9vbCkgew0KICAgICAgZGYkcG9vbF9pZFtpXSA8LSBwb29sX2lkICAjIENvbnRpbnVlIGFzc2lnbmluZyB0aGUgY3VycmVudCBwb29sIElEDQogICAgICANCiAgICAgICMgQ2hlY2sgaWYgdGhlIGN1cnJlbnQgcm93IGVuZHMgdGhlIHBvb2wNCiAgICAgIGlmICghaXMubmEoZGYkcmVzaWR1YWxfZGVwdGhbaV0pICYmIGRmJHJlc2lkdWFsX2RlcHRoW2ldIDw9IDApIHsNCiAgICAgICAgaWYgKCFpcy5uYShkZiRMRE1faWRbaV0pKSB7DQogICAgICAgICAgIyBJZiB0aGUgY3VycmVudCByb3cgaXMgYSBMRE0sIHN0YXJ0IGEgbmV3IHBvb2wNCiAgICAgICAgICBwb29sX2lkIDwtIHBvb2xfaWQgKyAxDQogICAgICAgICAgZGYkcG9vbF9pZFtpXSA8LSBwb29sX2lkICAjIEFzc2lnbiB0aGUgbmV3IHBvb2wgSUQNCiAgICAgICAgICAjIENvbnRpbnVlIGluX3Bvb2wgPSBUUlVFIHNpbmNlIGEgbmV3IHBvb2wgc3RhcnRzDQogICAgICAgIH0gZWxzZSB7DQogICAgICAgICAgIyBJZiB0aGUgY3VycmVudCByb3cgaXMgTk9UIGFuIExETSwgZW5kIHRoZSBwb29sDQogICAgICAgICAgaW5fcG9vbCA8LSBGQUxTRSAgIyBFeGl0IHRoZSBwb29sDQogICAgICAgIH0NCiAgICAgIH0NCiAgICB9DQogIH0NCiAgDQogIHJldHVybihkZikNCn0NCg0KIyBBcHBseSB0aGUgZnVuY3Rpb24gYWNyb3NzIGFsbCBTaXRlLVllYXIgY29tYmluYXRpb25zDQpyZXNpZHVhbHMuZGYgPC0gcmVzaWR1YWxzLmRmICU+JQ0KICBncm91cF9ieShTaXRlLCB5ZWFyKSAlPiUNCiAgZG8oaWRlbnRpZnlfcmVzaWR1YWxfcG9vbHMoLikpICU+JQ0KICB1bmdyb3VwKCkNCg0KIyBFbnN1cmUgcG9vbF9pZCBpcyBhIGZhY3RvciB3aXRoIG51bWVyaWMgb3JkZXJpbmcNCnJlc2lkdWFscy5kZiRwb29sX2lkIDwtIGZhY3RvcihyZXNpZHVhbHMuZGYkcG9vbF9pZCwgbGV2ZWxzID0gYXMuY2hhcmFjdGVyKHNvcnQoYXMubnVtZXJpYyh1bmlxdWUocmVzaWR1YWxzLmRmJHBvb2xfaWQpKSkpKQ0KDQojIEN1c3RvbSBwYWxldHRlIHdpdGggbW9yZSBkaXN0aW5jdCBjb2xvcnMgKHByaW9yaXR5IGlzIHRvIElEIHBvb2xzIGZyb20gYWRqYWNlbnQgb25lcykNCmN1c3RvbV9wYWxldHRlIDwtIGMoDQogICIjRTQxQTFDIiwgIiMzNzdFQjgiLCAiIzREQUY0QSIsICIjOTg0RUEzIiwgIiNGRjdGMDAiLCAiI0ZGRkYzMyIsICIjQTY1NjI4IiwgIiNGNzgxQkYiLCAiIzk5OTk5OSIsICIjNjZDMkE1IiwgIiNGQzhENjIiLCAiIzhEQTBDQiIsICIjRTc4QUMzIiwgIiNBNkQ4NTQiLCAiI0ZGRDkyRiIsICAgIiNFNUM0OTQiLCAiI0IzQjNCMyIsICIjMUI5RTc3IiwgIiNEOTVGMDIiKQ0KDQpnZzwtZ2dwbG90KHJlc2lkdWFscy5kZiwgYWVzKHggPSBkaXN0YW5jZSkpICsNCiAgZ2VvbV9saW5lKGFlcyh5ID0gLVRoYWx3ZWdfRGVwdGhfbSksIGNvbG9yID0gImJsYWNrIiwgbGluZXdpZHRoID0gMSwgbGluZXR5cGUgPSAic29saWQiKSArDQogIGdlb21fcG9pbnQoYWVzKHkgPSAtcmVzaWR1YWxfc3VyZmFjZSksIGNvbG9yID0gImJsdWUiLCBzaXplID0gMSkgKw0KICBnZW9tX3JpYmJvbihhZXMoeW1pbiA9IC1UaGFsd2VnX0RlcHRoX20sIHltYXggPSAtcmVzaWR1YWxfc3VyZmFjZSwgZmlsbCA9IHBvb2xfaWQpLCBhbHBoYSA9IDAuNikgKw0KICBsYWJzKHggPSAiRGlzdGFuY2UgKG0pIiwgeSA9ICJEZXB0aCAobSkiLCB0aXRsZSA9ICJSZXNpZHVhbCBQb29scyIsIGZpbGwgPSAiUG9vbCBJRCIpICsNCiAgc2NhbGVfeV9jb250aW51b3VzKA0KICAgIG5hbWUgPSAiRGVwdGggKG0pIiwgDQogICAgYnJlYWtzID0gc2VxKC1tYXgocmVzaWR1YWxzLmRmJFRoYWx3ZWdfRGVwdGhfbSwgbmEucm0gPSBUUlVFKSwgMCwgYnkgPSAwLjIpLA0KICAgIGxhYmVscyA9IHNjYWxlczo6bnVtYmVyX2Zvcm1hdChhY2N1cmFjeSA9IDAuMiwgYmlnLm1hcmsgPSAiIiwgZGVjaW1hbC5tYXJrID0gIi4iKSgNCiAgICAgIGFicyhzZXEoLW1heChyZXNpZHVhbHMuZGYkVGhhbHdlZ19EZXB0aF9tLCBuYS5ybSA9IFRSVUUpLCAwLCBieSA9IDAuMikpDQogICAgKQ0KICApICsNCiAgc2NhbGVfZmlsbF9tYW51YWwodmFsdWVzID0gY3VzdG9tX3BhbGV0dGUpICsNCiAgdGhlbWVfbWluaW1hbCgpICsNCiAgdGhlbWUoDQogICAgYXhpcy50ZXh0LnkgPSBlbGVtZW50X3RleHQoY29sb3IgPSAiYmxhY2siKSwNCiAgICBheGlzLnRpdGxlLnkgPSBlbGVtZW50X3RleHQoY29sb3IgPSAiYmxhY2siKSwNCiAgICBwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KGhqdXN0ID0gMC41KSwNCiAgICBzdHJpcC50ZXh0ID0gZWxlbWVudF90ZXh0KHNpemUgPSA4LCBmYWNlID0gImJvbGQiKSwNCiAgICBsZWdlbmQucG9zaXRpb24gPSAicmlnaHQiDQogICkgKw0KICBmYWNldF9ncmlkKFNpdGUgfiB5ZWFyLCBzY2FsZXMgPSAiZml4ZWQiKQ0KDQppbnRlcmFjdGl2ZV9wbG90IDwtIGdncGxvdGx5KGdnKQ0KaW50ZXJhY3RpdmVfcGxvdA0KDQojIEV4cG9ydCBhIGZpZ3VyZQ0KZXhwb3J0X3Bsb3QoZ2csICJEZXB0aCBhbmQgUmVzaWR1YWwgU3VyZmFjZSAtIFBvb2xzIElEZC5wZGYiKQ0KZXhwb3J0X3Bsb3QoaW50ZXJhY3RpdmVfcGxvdCwgIkRlcHRoIGFuZCBSZXNpZHVhbCBTdXJmYWNlIC0gUG9vbHMgSURkLmh0bWwiKQ0KYGBgDQoNClRoZSBhYm92ZSBmaWd1cmUgc2hvdWxkIHNob3cgYSBzZXJpZXMgb2YgZGlzdGluY3QgcG9vbHMgYW5kIGlzIGV4cG9ydGVkIHRvIHlvdXIgb3V0cHV0IGZvbGRlci4gRG9uJ3Qgd29ycnkgaWYgdGhlIHNoYWRpbmcgY3V0cyBvZmYgYmVmb3JlIHRoZSBwb29sJ3MgdXBzdHJlYW0gZXh0ZW50LCB0aGlzIGlzIGp1c3QgYW4gYXJ0ZWZhY3QgYXNzb2NpYXRlZCB3aXRoIG15IGxpbWl0ZWQgZmlndXJlLXBsb3R0aW5nIGFiaWxpdGllcy4gVGhlIGltcG9ydGFudCB0aGluZyB0byBub3RlIGlzIHRoYXQgdGhlIGNhbGN1bGF0aW9ucyBiZWxvdyB3aWxsIGludGVncmF0ZSB0aGUgZnVsbCBhcmVhIGJlbmVhdGggdGhlIHJlc2lkdWFsIHN1cmZhY2UgZm9yIGVhY2ggcG9vbC4NCg0KIyMgUG9vbCBNZXRyaWNzDQoNClRoZSBjb2RlIG5vdyBjYWxjdWxhdGVzIHRoZSBmb2xsb3dpbmcgbWV0cmljcyBmb3IgZWFjaCByZXNpZHVhbCBwb29sOg0KDQotIE1heGltdW0gZGVwdGg7DQoNCi0gUG9vbCBsZW5ndGggKHBvb2wgb3V0bGV0IHRvIHdoZXJlIHRoZSByZXNpZHVhbCBzdXJmYWNlIG1lZXRzIHRoZSB0aGFsd2VnIGF0IHRoZSB1cHN0cmVhbSBlbmQgb2YgdGhlIHBvb2wpOyBhbmQNCg0KLSBTYWdpdHRhbCBhcmVhLg0KDQpTYWdpdHRhbCByZWZlcnMgdG8gYSBwbGFuZSB0aGF0IGRpdmlkZXMgYSBib2R5IGludG8gbGVmdCBhbmQgcmlnaHQsIHNvIGltYWdpbmUgYSB0d28tZGltZW5zaW9uYWwgdmVydGljYWwgc2NyZWVuIGV4dGVuZGluZyBkb3duc3RyZWFtIGFsbCBhbG9uZyB0aGUgdGhhbHdlZywgc2VwYXJhdGluZyByaXZlciBsZWZ0IGZyb20gcml2ZXIgcmlnaHQuIFdpdGhpbiBlYWNoIHJlc2lkdWFsIHBvb2wsIHRoZSBzYWdpdHRhbCBhcmVhIGNvcnJlc3BvbmRzIHRvIHRoZSBzdXJmYWNlIGFyZWEgb2YgdGhhdCBzY3JlZW4uIFRvbyBhYnN0cmFjdD8gVGFrZSBhIGxvb2sgYXQgdGhlIGFib3ZlIGZpZ3VyZSBhZ2FpbjogRWFjaCBvZiB0aGUgc2hhZGVkIGFyZWFzIGNvcnJlc3BvbmRzIHRvIHRoZSBzYWdpdHRhbCBhcmVhIGZvciB0aGF0IHBhcnRpY3VsYXIgcmVzaWR1YWwgcG9vbCAtIHNhZ2l0dGFsIGFyZWEgaW50ZWdyYXRlcyBlYWNoIGRlcHRoIG1lYXN1cmVtZW50IG92ZXIgdGhlIGxlbmd0aCBvZiB0aGUgcG9vbC4gQWx0aG91Z2ggdGhpcyBtYXkgbm90IGJlIGFzIGludHVpdGl2ZSBhcyBwb29sIHZvbHVtZSwgaXQgcmVxdWlyZXMgZmV3ZXIgYXNzdW1wdGlvbnMgdGhhbiB3aWxsIGJlIG5lY2Vzc2FyeSB0byBnZW5lcmF0ZSBlc3RpbWF0ZXMgb2YgcG9vbCB2b2x1bWUgKGkuZS4sIHJlZ2FyZGluZyBjcm9zcy1zZWN0aW9uYWwgY2hhbm5lbCBzaGFwZSBvZiBwb29scyBhdCB6ZXJvIGZsb3csIHdldHRlZCB3aWR0aHMpLiBCZWNhdXNlIGZld2VyIGFzc3VtcHRpb25zIGFyZSByZXF1aXJlZCwgYW5kIGJlY2F1c2UgaXQgZWFzaWx5IGNvcnJlc3BvbmRzIHRvIDJEIHZpc3VhbGlzYXRpb25zIGxpa2UgdGhlIG9uZSBhYm92ZSwgd2UgcmVjb21tZW5kIHVzaW5nIHNhZ2l0dGFsIGFyZWEgcmF0aGVyIHRoYW4gdm9sdW1lIGZvciBhIG1ldHJpYyB0cmFja2luZyBjaGFuZ2VzIGluIHBvb2wgaGFiaXRhdCAodGhvdWdoIHdlIHdpbGwgYWxzbyBjYWxjdWxhdGUgdm9sdW1lIGxhdGVyKS4NCg0KYGBge3Igc2FnaXR0YWwgYXJlYSwgbWF4IGRlcHRocywgcG9vbCBsZW5ndGhzLCBlY2hvID0gRkFMU0V9DQpjcmVhdGVfcG9vbF9zdW1tYXJ5X3RhYmxlIDwtIGZ1bmN0aW9uKHJlc2lkdWFscy5kZiwgY3VzdG9tX2RlcHRoX3RocmVzaG9sZCA9IE5VTEwpIHsNCiAgIyBSZW1vdmUgcm93cyB3aXRoIG5lZ2F0aXZlIGRpc3RhbmNlIHZhbHVlcw0KICByZXNpZHVhbHMuZGYgPC0gcmVzaWR1YWxzLmRmW3Jlc2lkdWFscy5kZiRkaXN0YW5jZSA+PSAwLCBdDQogIA0KICAjIEVuc3VyZSB0aGUgZGF0YWZyYW1lIGlzIHNvcnRlZCBieSBkaXN0YW5jZQ0KICByZXNpZHVhbHMuZGYgPC0gcmVzaWR1YWxzLmRmW29yZGVyKHJlc2lkdWFscy5kZiRkaXN0YW5jZSksIF0NCiAgDQogICMgRmlsdGVyIG91dCByb3dzIHdoZXJlIHBvb2xfaWQgaXMgTkENCiAgcmVzaWR1YWxzLmRmIDwtIHJlc2lkdWFscy5kZlshaXMubmEocmVzaWR1YWxzLmRmJHBvb2xfaWQpLCBdDQogIA0KICAjIEluaXRpYWxpemUgYSBsaXN0IHRvIHN0b3JlIHJlc3VsdHMgZm9yIGVhY2ggc2l0ZS15ZWFyIGNvbWJpbmF0aW9uDQogIHBvb2xfc3VtbWFyeV9saXN0IDwtIGxpc3QoKQ0KDQogICMgR3JvdXAgdGhlIGRhdGFmcmFtZSBieSBTaXRlIGFuZCBZZWFyDQogIHJlc2lkdWFscy5kZl9ncm91cGVkIDwtIHNwbGl0KHJlc2lkdWFscy5kZiwgbGlzdChyZXNpZHVhbHMuZGYkU2l0ZSwgcmVzaWR1YWxzLmRmJHllYXIpKQ0KICANCiAgIyBJdGVyYXRlIG92ZXIgZWFjaCBTaXRlLVllYXIgZ3JvdXANCiAgZm9yIChncm91cF9uYW1lIGluIG5hbWVzKHJlc2lkdWFscy5kZl9ncm91cGVkKSkgew0KICAgIGdyb3VwIDwtIHJlc2lkdWFscy5kZl9ncm91cGVkW1tncm91cF9uYW1lXV0NCiAgICANCiAgICAjIENhbGN1bGF0ZSB0aGUgc3RhbmRhcmQgZGV2aWF0aW9uIG9mIHJlc2lkdWFsIGRlcHRocyBmb3IgdGhpcyBncm91cA0KICAgIHNkX3Jlc2lkdWFsX2RlcHRoIDwtIHNkKGdyb3VwJHJlc2lkdWFsX2RlcHRoLCBuYS5ybSA9IFRSVUUpDQogICAgDQogICAgIyBJbml0aWFsaXplIGEgbGlzdCB0byBzdG9yZSByZXN1bHRzIGZvciBlYWNoIHBvb2wgaW4gdGhlIGN1cnJlbnQgZ3JvdXANCiAgICBwb29sX3N1bW1hcnkgPC0gbGlzdCgpDQogICAgDQogICAgIyBJdGVyYXRlIG92ZXIgdW5pcXVlIHBvb2xfaWRzIHRvIGNhbGN1bGF0ZSBtYXggcmVzaWR1YWwgZGVwdGggYW5kIHNhZ2l0dGFsIGFyZWEgZm9yIGVhY2ggcG9vbA0KICAgIHVuaXF1ZV9wb29sX2lkcyA8LSB1bmlxdWUoZ3JvdXAkcG9vbF9pZCkNCiAgICBmb3IgKHBvb2xfaWQgaW4gdW5pcXVlX3Bvb2xfaWRzKSB7DQogICAgICAjIFN1YnNldCB0aGUgZGF0YWZyYW1lIGZvciB0aGUgY3VycmVudCBwb29sDQogICAgICBwb29sX2RhdGEgPC0gZ3JvdXBbZ3JvdXAkcG9vbF9pZCA9PSBwb29sX2lkLCBdDQogICAgICANCiAgICAgICMgQ2FsY3VsYXRlIHRoZSBtYXhpbXVtIHJlc2lkdWFsIGRlcHRoIGZvciB0aGUgcG9vbA0KICAgICAgbWF4X3Jlc2lkdWFsX2RlcHRoIDwtIG1heChwb29sX2RhdGEkcmVzaWR1YWxfZGVwdGgsIG5hLnJtID0gVFJVRSkNCiAgICAgIA0KICAgICAgIyBBcHBseSBzZWxlY3Rpb24gY3JpdGVyaWE6IGVpdGhlciB0aGUgbWF4IHJlc2lkdWFsIGRlcHRoIGlzID49IHNkIG9yIHRoZSBjdXN0b20gdGhyZXNob2xkIGlzIG1ldA0KICAgICAgaWYgKCFpcy5udWxsKGN1c3RvbV9kZXB0aF90aHJlc2hvbGQpKSB7DQogICAgICAgICMgVXNlIHRoZSBjdXN0b20gZGVwdGggdGhyZXNob2xkIGZvciBzZWxlY3Rpb24NCiAgICAgICAgaWYgKG1heF9yZXNpZHVhbF9kZXB0aCA8IGN1c3RvbV9kZXB0aF90aHJlc2hvbGQpIHsNCiAgICAgICAgICBuZXh0ICAjIFNraXAgdGhpcyBwb29sIGlmIGl0IGRvZXNuJ3QgbWVldCB0aGUgY3VzdG9tIHRocmVzaG9sZA0KICAgICAgICB9DQogICAgICB9IGVsc2Ugew0KICAgICAgICAjIFVzZSB0aGUgc3RhbmRhcmQgZGV2aWF0aW9uIG9mIHRoZSBncm91cCBmb3Igc2VsZWN0aW9uIGlmIG5vIGN1c3RvbSB0aHJlc2hvbGQgaXMgcHJvdmlkZWQNCiAgICAgICAgaWYgKG1heF9yZXNpZHVhbF9kZXB0aCA8IHNkX3Jlc2lkdWFsX2RlcHRoKSB7DQogICAgICAgICAgbmV4dCAgIyBTa2lwIHRoaXMgcG9vbCBpZiBpdCBkb2Vzbid0IG1lZXQgdGhlIFNEIHRocmVzaG9sZA0KICAgICAgICB9DQogICAgICB9DQogICAgICANCiAgICAgICMgSW5pdGlhbGl6ZSB2YXJpYWJsZSB0byBhY2N1bXVsYXRlIGFyZWEgZm9yIHRoaXMgcG9vbA0KICAgICAgc2FnaXR0YWxfYXJlYSA8LSAwDQogICAgICANCiAgICAgICMgSXRlcmF0ZSB0aHJvdWdoIHRoZSBkYXRhZnJhbWUgZm9yIHRoaXMgcG9vbCBhbmQgY2FsY3VsYXRlIHRoZSBhcmVhDQogICAgICBmb3IgKGkgaW4gMToobnJvdyhwb29sX2RhdGEpIC0gMSkpIHsgICMgbG9vcCB0byBhdm9pZCBvdXQtb2YtYm91bmRzIGluZGV4DQogICAgICAgIHJlc2lkdWFsX2RlcHRoIDwtIHBvb2xfZGF0YSRyZXNpZHVhbF9kZXB0aFtpXQ0KICAgICAgICANCiAgICAgICAgIyBTa2lwIHRoZSBpdGVyYXRpb24gaWYgcmVzaWR1YWwgZGVwdGggaXMgTkEgDQogICAgICAgIGlmIChpcy5uYShyZXNpZHVhbF9kZXB0aCkpIHsNCiAgICAgICAgICBuZXh0ICAjIFNraXAgdG8gdGhlIG5leHQgaXRlcmF0aW9uIGlmIHJlc2lkdWFsIGRlcHRoIGlzIE5BDQogICAgICAgIH0NCiAgICAgICAgDQogICAgICAgICMgQ2FsY3VsYXRlIHRoZSBzcGFjaW5nIChkaXN0YW5jZSkgYmV0d2VlbiB0aGUgY3VycmVudCBhbmQgZm9sbG93aW5nIHBvaW50cw0KICAgICAgICBzcGFjaW5nIDwtIGFicyhwb29sX2RhdGEkZGlzdGFuY2VbaSArIDFdIC0gcG9vbF9kYXRhJGRpc3RhbmNlW2ldKQ0KICAgICAgICANCiAgICAgICAgIyBBZGQgdG8gdGhlIGFyZWEgaWYgcmVzaWR1YWwgZGVwdGggaXMgZ3JlYXRlciB0aGFuIDANCiAgICAgICAgc2FnaXR0YWxfYXJlYSA8LSBzYWdpdHRhbF9hcmVhICsgKHJlc2lkdWFsX2RlcHRoICogc3BhY2luZykNCiAgICAgIH0NCiAgICAgIA0KICAgICAgIyBIYW5kbGUgdGhlIGxhc3Qgcm93IGNvbnRyaWJ1dGlvbiB0byBzYWdpdHRhbCBhcmVhDQogICAgICBsYXN0X3JvdyA8LSBwb29sX2RhdGFbbnJvdyhwb29sX2RhdGEpLCBdDQogICAgICBpZiAoIWlzLm5hKGxhc3Rfcm93JHJlc2lkdWFsX2RlcHRoKSAmJiBsYXN0X3JvdyRyZXNpZHVhbF9kZXB0aCA+IDApIHsNCiAgICAgICAgbmV4dF9wb29sX3N0YXJ0IDwtIGdyb3VwW2dyb3VwJGRpc3RhbmNlID4gbGFzdF9yb3ckZGlzdGFuY2UgJiAhaXMubmEoZ3JvdXAkcG9vbF9pZCksIF0NCiAgICAgICAgaWYgKG5yb3cobmV4dF9wb29sX3N0YXJ0KSA+IDApIHsNCiAgICAgICAgICBuZXh0X2Rpc3RhbmNlIDwtIG5leHRfcG9vbF9zdGFydCRkaXN0YW5jZVsxXQ0KICAgICAgICAgIHNwYWNpbmcgPC0gYWJzKG5leHRfZGlzdGFuY2UgLSBsYXN0X3JvdyRkaXN0YW5jZSkNCiAgICAgICAgICBzYWdpdHRhbF9hcmVhIDwtIHNhZ2l0dGFsX2FyZWEgKyAobGFzdF9yb3ckcmVzaWR1YWxfZGVwdGggKiBzcGFjaW5nKQ0KICAgICAgICB9DQogICAgICB9DQogICAgICANCiAgICAgICMgQ2FsY3VsYXRlIHRoZSBwb29sIGxlbmd0aA0KICAgICAgbWluX2Rpc3RhbmNlIDwtIG1pbihwb29sX2RhdGEkZGlzdGFuY2UsIG5hLnJtID0gVFJVRSkNCiAgICAgIG1heF9kaXN0YW5jZSA8LSBtYXgocG9vbF9kYXRhJGRpc3RhbmNlLCBuYS5ybSA9IFRSVUUpDQogICAgICBwb29sX2xlbmd0aCA8LSBpZmVsc2UobWluX2Rpc3RhbmNlIDwgMCwgbWF4X2Rpc3RhbmNlLCBtYXhfZGlzdGFuY2UgLSBtaW5fZGlzdGFuY2UpDQogICAgICANCiAgICAgICMgU3RvcmUgdGhlIHJlc3VsdHMgZm9yIHRoZSBjdXJyZW50IHBvb2wNCiAgICAgIHBvb2xfc3VtbWFyeVtbYXMuY2hhcmFjdGVyKHBvb2xfaWQpXV0gPC0gbGlzdChtYXhfcmVzaWR1YWxfZGVwdGggPSBtYXhfcmVzaWR1YWxfZGVwdGgsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2FnaXR0YWxfYXJlYSA9IHNhZ2l0dGFsX2FyZWEsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcG9vbF9sZW5ndGggPSBwb29sX2xlbmd0aCkNCiAgICB9DQogICAgDQogICAgIyBDb252ZXJ0IHRoZSByZXN1bHRzIGludG8gYSBkYXRhIGZyYW1lIGZvciB0aGUgY3VycmVudCBzaXRlLXllYXIgY29tYmluYXRpb24NCiAgICBwb29sX3N1bW1hcnlfZGYgPC0gZGF0YS5mcmFtZShwb29sX2lkID0gbmFtZXMocG9vbF9zdW1tYXJ5KSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtYXhfcmVzaWR1YWxfZGVwdGggPSBzYXBwbHkocG9vbF9zdW1tYXJ5LCBmdW5jdGlvbih4KSB4JG1heF9yZXNpZHVhbF9kZXB0aCksDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2FnaXR0YWxfYXJlYSA9IHNhcHBseShwb29sX3N1bW1hcnksIGZ1bmN0aW9uKHgpIHgkc2FnaXR0YWxfYXJlYSksDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcG9vbF9sZW5ndGggPSBzYXBwbHkocG9vbF9zdW1tYXJ5LCBmdW5jdGlvbih4KSB4JHBvb2xfbGVuZ3RoKSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBTaXRlID0gdW5pcXVlKGdyb3VwJFNpdGUpLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHllYXIgPSB1bmlxdWUoZ3JvdXAkeWVhcikpDQogICAgDQogICAgIyBBcHBlbmQgdGhpcyBzdW1tYXJ5IHRvIHRoZSBtYWluIHBvb2xfc3VtbWFyeV9saXN0DQogICAgcG9vbF9zdW1tYXJ5X2xpc3RbW2dyb3VwX25hbWVdXSA8LSBwb29sX3N1bW1hcnlfZGYNCiAgfQ0KICANCiAgIyBDb21iaW5lIGFsbCBzaXRlLXllYXIgcG9vbCBzdW1tYXJpZXMgaW50byBhIHNpbmdsZSBkYXRhZnJhbWUNCiAgZmluYWxfcG9vbF9zdW1tYXJ5X2RmIDwtIGRvLmNhbGwocmJpbmQsIHBvb2xfc3VtbWFyeV9saXN0KQ0KICANCiAgIyBBZGQgY3VzdG9tX2RlcHRoX3RocmVzaG9sZCBhcyBhbiBhdHRyaWJ1dGUgdG8gdGhlIGRhdGEgZnJhbWUNCiAgYXR0cihmaW5hbF9wb29sX3N1bW1hcnlfZGYsICJjdXN0b21fZGVwdGhfdGhyZXNob2xkIikgPC0gY3VzdG9tX2RlcHRoX3RocmVzaG9sZA0KICANCiAgIyBSZXR1cm4gdGhlIGZpbmFsIHN1bW1hcnkgdGFibGUNCiAgcmV0dXJuKGZpbmFsX3Bvb2xfc3VtbWFyeV9kZikNCn0NCg0KIyB0aGlzIGlzIGEgZnVuY3Rpb24uIEl0IGRvZXMgbm90IGFjdHVhbGx5IHByb2R1Y2UgYSBuZXcgZGF0YWZyYW1lIHlldC4gVGhlIG5leHQgY2h1bmsgd2lsbC4uLg0KYGBgDQoNCiMjIFN1YnNldHRpbmcgUG9vbHMNCg0KU28gZmFyIHdlIGhhdmUgaWRlbnRpZmllZCBhbGwgb2YgdGhlIHJlc2lkdWFsIHBvb2xzLCBidXQgZGVwZW5kaW5nIG9uIHlvdXIgZGF0YXNldCBzb21lIG9mIHRoZSBwb29scyB2aXN1YWxpc2VkIGFib3ZlIG1pZ2h0IGxvb2sgbW9yZSBsaWtlIHB1ZGRsZXMuIFNvIHRvIGZvY3VzIG91ciBzdW1tYXJ5IHN0YXRpc3RpY3Mgb24gcG9vbHMgdGhhdCBiZXR0ZXIgYWxpZ24gd2l0aCB3aGF0IHdlIGNvbnNpZGVyIGJpb2xvZ2ljYWxseS0gYW5kL29yIGdlb21vcnBoaWNhbGx5LW1lYW5pbmdmdWwsIHdlIGNhbiB1c2UgdGhlIG1ldHJpY3Mgd2UganVzdCBjYWxjdWxhdGVkIHRvIGZvY3VzIG9uIGEgc3BlY2lmaWMgc3Vic2V0IG9mIGRlZXBlciBwb29scy4NCg0KSW4gdGVybXMgb2Ygc3Vic2V0dGluZyBwb29scywgc29tZSBwZW9wbGUgdXNlIGEgc3BlY2lmaWMgZGVwdGggY3V0LW9mZiBmb3IgYSBzcGVjaWVzIG9mIGludGVyZXN0IChlLmcuLCBNb3Nzb3AgYW5kIEJyYWRmb3JkIDIwMDYgdXNlZCAwLjEgbSkuIEFsdGVybmF0aXZlbHkgdGhlIHBvb2xzIHRoYXQgd2UgZm9jdXMgb24gY2FuIGJlIGJhc2VkIG9uIHBoeXNpY2FsIGNoYXJhY3RlcmlzdGljcyBvZiB0aGUgc2FtcGxlZCByZWFjaC4gV2Ugd2lsbCBkbyB0aGUgbGF0dGVyLCBrZWVwaW5nIHRoaXMgY29kZSBtb3JlIHdpZGVseSBhcHBsaWNhYmxlLCBieSBmb2xsb3dpbmcgU3RhY2sgKDE5ODkpIHdobyBkZXRlcm1pbmVkIG1lYW5pbmdmdWwgcG9vbHMgYXMgdGhvc2UgdGhhdCBoYWQgYSBtYXhpbXVtIGRlcHRoIGdyZWF0ZXIgdGhhbiBvciBlcXVhbCB0byB0aGUgc3RhbmRhcmQgZGV2aWF0aW9uIG9mIGRlcHRoIGZvciB0aGUgcmVhY2guIA0KDQpJbiB0aGUgZm9sbG93aW5nIGNvZGUgY2h1bmsgaXQgcmVhZHMgJ2N1c3RvbV9kZXB0aCA8LSBOVUxMJy4gVGhpcyBpcyBvdXIgZGVmYXVsdCBzdWJzZXR0aW5nIChzZWxlY3RzIG9ubHkgcG9vbHMgd2l0aCBhIG1heGltdW0gcmVzaWR1YWwgZGVwdGggZ3JlYXRlciB0aGFuIHRoZSBzdGFuZGFyZCBkZXZpYXRpb24gb2YgdGhlIHJlc2lkdWFsIGRlcHRocyBmb3IgdGhlIGVudGlyZSBzYW1wbGVkIHJlYWNoKS4gSWYgeW91IHdhbnQgdG8gc3Vic2V0IHRoZSBwb29scyBpbiBhbm90aGVyIHdheSwgeW91IGNhbiBtb2RpZnkgdGhlIGNvZGUgaGVyZS4gRm9yIGV4YW1wbGUsIGlmIGl0IGlzIGJpb2xvZ2ljYWxseSBtZWFuaW5nZnVsIGZvciB5b3VyIHN5c3RlbSB0byBjb25zaWRlciBvbmx5IHBvb2xzIHRoYXQgYXJlIDAuMSBtIGRlZXAgb3IgZ3JlYXRlciBkdXJpbmcgYXBwcm9hY2hpbmctemVyby1mbG93IHBlcmlvZHMsIHlvdSBjYW4gc3BlY2lmeSAnY3VzdG9tX2RlcHRoIDwtIDAuMScuIE9yLCBpZiB5b3Ugd2FudCB0byBjb25zaWRlciBhbGwgcG9vbHMgbm8gbWF0dGVyIGhvdyBzaGFsbG93LCB0aGVuIGFzc2lnbiBjdXN0b21fZGVwdGggYSB2YWx1ZSBvZiAnMCcuIEp1c3QgYmUgc3VyZSB0byBjb21wYXJlIGxpa2UtZm9yLWxpa2Ugd2hlbiB5b3UgY29uc2lkZXIgZGlmZmVyZW50IHllYXJzL3NpdGVzIHRoYXQgeW91IG1heSB3aXNoIHRvIGNvbXBhcmUuDQoNCmBgYHtyIGN1c3RvbSBkZXB0aCB0aHJlc2hvbGR9DQojIEFkZCBhIGN1c3RvbSBkZXB0aCB0aHJlc2hvbGQgaW4gbWV0cmVzLCBvciBsZWF2ZSBhcyAnTlVMTCcgdG8gdXNlIHN0YW5kYXJkIGRldmlhdGlvbi4gSWYgeW91IGFyZSBpbnRlcmVzdGVkIGluIGFsbCBvZiB0aGUgcmVzaWR1YWwgZGVwdGhzIChpLmUuLCBub3Qgc3Vic2V0dGluZyksIGp1c3QgZW50ZXIgJzAnIGZvciB0aGUgY3VzdG9tX2RlcHRoDQpjdXN0b21fZGVwdGggPC0gTlVMTA0KYGBgDQoNCmBgYHtyIHRhYmxlIG9mIG1heCBkZXB0aCwgc2FnaXR0YWwgYXJlYSwgcG9vbCBsZW5ndGgsIGVjaG8gPSBGQUxTRX0NCnBvb2xfc3VtbWFyeV9yZXN1bHQgPC0gY3JlYXRlX3Bvb2xfc3VtbWFyeV90YWJsZShyZXNpZHVhbHMuZGYsIGN1c3RvbV9kZXB0aF90aHJlc2hvbGQgPSBjdXN0b21fZGVwdGgpDQpwb29sX3N1bW1hcnlfcmVzdWx0JHBvb2xfaWQgPC0gYXMuY2hhcmFjdGVyKHBvb2xfc3VtbWFyeV9yZXN1bHQkcG9vbF9pZCkNCnBvb2xfc3VtbWFyeV9yZXN1bHQgPC0gcG9vbF9zdW1tYXJ5X3Jlc3VsdCAlPiUNCiAgc2VsZWN0KFNpdGUsIHllYXIsIGV2ZXJ5dGhpbmcoKSkgICMgTW92ZSBTaXRlIGFuZCBZZWFyIHRvIHRoZSBsZWZ0DQpkYXRhdGFibGUoDQogIHBvb2xfc3VtbWFyeV9yZXN1bHQsDQogIGNhcHRpb24gPSAiUmVzaWR1YWwgUG9vbCBTdW1tYXJ5IGJ5IFBvb2w6IE1heGltdW0gRGVwdGgsIExlbmd0aCwgU2FnaXR0YWwgQXJlYSIsDQogIHJvd25hbWVzID0gRkFMU0UsICAjIEhpZGUgcm93IG51bWJlcnMNCiAgb3B0aW9ucyA9IGxpc3QoDQogICAgcGFnZUxlbmd0aCA9IDEwLCAgIyBOdW1iZXIgb2Ygcm93cyBwZXIgcGFnZQ0KICAgIGF1dG9XaWR0aCA9IFRSVUUNCiAgKQ0KKSU+JQ0KICBmb3JtYXRSb3VuZChjb2x1bW5zID0gbmFtZXMocG9vbF9zdW1tYXJ5X3Jlc3VsdClbc2FwcGx5KHBvb2xfc3VtbWFyeV9yZXN1bHQsIGlzLm51bWVyaWMpXSwgZGlnaXRzID0gMykNCg0KIyBFeHBvcnQgdGFibGUNCmV4cG9ydF90YWJsZShhcy5kYXRhLmZyYW1lKHBvb2xfc3VtbWFyeV9yZXN1bHQpLCAiUmVzaWR1YWwgUG9vbCBJbmRpdmlkdWFsIE1heCBEZXB0aCBMZW5ndGggU2FnaXR0YWwuY3N2IikNCmBgYA0KDQpUaGUgdGFibGUgYWJvdmUgaGFzIGJlZW4gZXhwb3J0ZWQgdG8geW91ciBvdXRwdXQgZm9sZGVyLiBJdCBkaXNwbGF5cyB0aGUgc3Vic2V0IHNlbGVjdGlvbiBvZiByZXNpZHVhbCBwb29scywgdGhlIHNhZ2l0dGFsIGFyZWEgb2YgZWFjaCBwb29sLCB0aGUgbWF4aW11bSByZXNpZHVhbCBkZXB0aCAoZGVlcGVzdCBwb2ludCBwZXIgcG9vbCBhdCB6ZXJvIGZsb3cpLCBhbmQgdGhlIHBvb2wgbGVuZ3RoIG9mIGVhY2ggcG9vbC4gV2hlbiBjb25zaWRlcmVkIGF0IHRoZSByZWFjaC1zY2FsZSwgc3VtbWFyeSBzdGF0aXN0aWNzIG9mIHRoZSBtYXhpbXVtIHJlc2lkdWFsIGRlcHRoIGFuZCBwb29sIGxlbmd0aCBoYXZlIGJlZW4gY29uc2lkZXJlZCB1c2VmdWwgbWV0cmljcyB0byB0cmFjayBwb29sIHF1YWxpdHkgYW5kIHF1YW50aXR5IChlLmcuLCBMaXNsZSAxOTg2LCBNb3Nzb3AgYW5kIEJyYWRmb3JkIDIwMDYsIENsYXJrIGV0IGFsIDIwMTkpLg0KDQpUaGUgcmVhY2ggbWVhbiBvZiB0aGUgcG9vbCBtYXhpbXVtIHJlc2lkdWFsIGRlcHRocyBoYXMgYmVlbiB1c2VkIGFzIGEgcHJveHkgZm9yIHBvb2wgcXVhbGl0eSwgYW5kIHBvc2l0aXZlIHJlbGF0aW9uc2hpcHMgd2l0aCBDaGlub29rIHNhbG1vbiBkZW5zaXR5IGhhdmUgYmVlbiBkZW1vbnN0cmF0ZWQgKGUuZy4sIE1vc3NvcCBhbmQgQnJhZGZvcmQgMjAwNikuIFJlbGF0aW9uc2hpcHMgYmV0d2VlbiBoYWJpdGF0IG1ldHJpY3MgYW5kIGJpb3RhIGNhbiBiZSBoaWdobHkgY29udGV4dC1kZXBlbmRlbnQsIGFuZCBpbmRlcGVuZGVudCB2ZXJpZmljYXRpb24gaXMgcmVjb21tZW5kZWQgd2hlcmUgcG9zc2libGUuIEhvd2V2ZXIsIGFzIHRoZSByZXNvdXJjZXMgcmVxdWlyZWQgdG8gdGVzdCB0aGVzZSBhc3N1bXB0aW9ucyBhcmUgb2Z0ZW4gcHJvaGliaXRpdmUsIHdlIHJlY29tbWVuZCB0YWtpbmcgYWR2YW50YWdlIG9mIHJlbGF0aW9uc2hpcHMgdGhhdCBoYXZlIGFscmVhZHkgYmVlbiBxdWFudGl0YXRpdmVseSBkZW1vbnN0cmF0ZWQgaW4gdGhlIHNjaWVudGlmaWMgbGl0ZXJhdHVyZS4gQWx0aG91Z2ggaXQgKmlzKiBwb3NzaWJsZSB0byBnZW5lcmF0ZSBxdWFudGl0YXRpdmUgZXN0aW1hdGVzIG9mIGJpb3RpYyBkZW5zaXRpZXMgaWYgdGhlIHJlbGF0aW9uc2hpcCBiZXR3ZWVuIGhhYml0YXQgbWV0cmljIGFuZCBiaW90aWMgZGVuc2l0eSBpcyBtb25vdG9uaWMsIHdlIGZlZWwgdGhhdCB0aGlzIGlzIHRvbyBzcGVjdWxhdGl2ZSB3aXRob3V0IGRhdGEgZm9yIHlvdXIgaW5kaXZpZHVhbCBzeXN0ZW0uIEhvd2V2ZXIsIGZvciB0aGUgcHVycG9zZSBvZiByZXN0b3JhdGlvbiBtb25pdG9yaW5nLCB3ZSBmZWVsIGl0IGlzIGluY3JlZGlibHkgcG93ZXJmdWwgdG8gYmUgYWJsZSB0byBkZW1vbnN0cmF0ZSAoZS5nLikgdGhhdCB3ZSBoYXZlIGNhdXNlZCBhbiAqeCotc2l6ZWQgaW5jcmVhc2UgaW4gYSBoYWJpdGF0IG1ldHJpYyB0aGF0IGlzIGtub3duIHRvIGJlIHBvc2l0aXZlbHkgY29ycmVsYXRlZCB3aXRoIHRhcmdldCBzcGVjaWVzIGRlbnNpdHkgaW4gYSBzaW1pbGFyIHN5c3RlbS4gDQoNClRoZSBwcm9wb3J0aW9uYWwgbGVuZ3RoIG9mIHBvb2xzIGluIHRoZSByZWFjaCBhbHNvIGhhcyBkZW1vbnN0cmF0ZWQgcG9zaXRpdmUgcmVsYXRpb25zaGlwcyB3aXRoIGNvaG8sIENoaW5vb2sgZGVuc2l0aWVzIChDbGFyayBldCBhbCAyMDE5KS4gQmVhciBpbiBtaW5kIHRoYXQgdGhlcmUgd2lsbCBhbHdheXMgYmUgbnVhbmNlIGludm9sdmVkIGluIHRoZSBhcHBsaWNhdGlvbiBhbmQgaW50ZXJwcmV0YXRpb24gb2YgaGFiaXRhdCBtZXRyaWNzLiBZb3UgbXVzdCB1bmRlcnN0YW5kIGFuZCBwcmVkaWN0LCBpbiBhbiAqYSBwcmlvcmkqIGZhc2hpb24sIHdoYXQgeW91ciByZXN0b3JhdGlvbiBvYmplY3RpdmVzIGFyZSB3aXRoIHJlc3BlY3QgdG8gaGFiaXRhdDogRG9lcyB5b3VyIHJlYWNoIG5lZWQgbW9yZSBwb29sIG9mIGEgY2VydGFpbiBkZXB0aD8gSXMgeW91ciByZWFjaCBsYWNraW5nIG11Y2gtbmVlZGVkIHJpZmZsZXM/IFByZXN1bWFibHkgdGhlcmUgYXJlIGNhc2VzIHdoZXJlIHRoZSByZWFjaCBoYXMgdG9vIG11Y2ggcG9vbCBoYWJpdGF0LiBUaGVzZSB0eXBlcyBvZiBxdWVzdGlvbnMgYXJlIGJlc3QgYWRkcmVzc2VkIHdpdGggd2VsbC1tYXRjaGVkIHJlZmVyZW5jZSBzaXRlcywgYnV0IGxvY2FsIGtub3dsZWRnZSBhbmQgdGhlIHNjaWVudGlmaWMgbGl0ZXJhdHVyZSB3aWxsIGFsc28gYmUgb2YgZ3JlYXQgaGVscC4NCg0KV2Ugd2lsbCBub3cgZ2VuZXJhdGUgYW5kIGV4cG9ydCB0byB5b3VyIG91dHB1dCBmb2xkZXIgc29tZSBzdW1tYXJ5IHN0YXRpc3RpY3MsIGluY2x1ZGluZyB0aGUgYWZvcmVtZW50aW9uZWQgbWVhbiBtYXggcmVzaWR1YWwgZGVwdGggYW5kIGxlbmd0aCBpbiByZXNpZHVhbCBwb29sLCBmb3IgeW91ciBkYXRhOg0KDQpgYGB7ciByZXNpZHVhbCBwb29sIHN1bW1hcnkgc3RhdHMsIGVjaG8gPSBGQUxTRX0NCiMgRnVuY3Rpb24gdG8gY2FsY3VsYXRlIHN1bW1hcnkgc3RhdGlzdGljcyBmb3IgdGhlIHN1YnNldCBvZiBwb29scywgZ3JvdXBlZCBieSBTaXRlIGFuZCBZZWFyDQpjYWxjdWxhdGVfc3Vic2V0X3N1bW1hcnkgPC0gZnVuY3Rpb24ocG9vbF9zdW1tYXJ5X2RmLCByZXNpZHVhbHMuZGYpIHsNCiAgIyBJbml0aWFsaXplIGEgbGlzdCB0byBzdG9yZSB0aGUgcmVzdWx0cyBmb3IgZWFjaCBTaXRlLVllYXIgY29tYmluYXRpb24NCiAgc3Vic2V0X3N1bW1hcnlfbGlzdCA8LSBsaXN0KCkNCiAgDQogICMgR3JvdXAgdGhlIHBvb2wgc3VtbWFyeSBkYXRhZnJhbWUgYnkgU2l0ZSBhbmQgWWVhcg0KICBwb29sX3N1bW1hcnlfZ3JvdXBlZCA8LSBzcGxpdChwb29sX3N1bW1hcnlfZGYsIGxpc3QocG9vbF9zdW1tYXJ5X2RmJFNpdGUsIHBvb2xfc3VtbWFyeV9kZiR5ZWFyKSkNCiAgDQogICMgSXRlcmF0ZSBvdmVyIGVhY2ggU2l0ZS1ZZWFyIGdyb3VwDQogIGZvciAoZ3JvdXBfbmFtZSBpbiBuYW1lcyhwb29sX3N1bW1hcnlfZ3JvdXBlZCkpIHsNCiAgICBncm91cCA8LSBwb29sX3N1bW1hcnlfZ3JvdXBlZFtbZ3JvdXBfbmFtZV1dDQogICAgDQogICAgIyBFbnN1cmUgdGhlIGdyb3VwIGhhcyB2YWxpZCBgU2l0ZWAgYW5kIGB5ZWFyYCB2YWx1ZXMNCiAgICBzaXRlIDwtIHVuaXF1ZShncm91cCRTaXRlKQ0KICAgIHllYXIgPC0gdW5pcXVlKGdyb3VwJHllYXIpDQogICAgDQogICAgaWYgKGxlbmd0aChzaXRlKSAhPSAxIHx8IGxlbmd0aCh5ZWFyKSAhPSAxKSB7DQogICAgICB3YXJuaW5nKHNwcmludGYoIlNraXBwaW5nIGdyb3VwICclcycgZHVlIHRvIGluY29uc2lzdGVudCBTaXRlIG9yIFllYXIuIiwgZ3JvdXBfbmFtZSkpDQogICAgICBuZXh0DQogICAgfQ0KICAgIA0KICAgICMgQ2FsY3VsYXRlIHRvdGFsIHNhZ2l0dGFsIGFyZWEgZm9yIHRoZSBzdWJzZXQgb2YgcG9vbHMgaW4gdGhpcyBncm91cA0KICAgIHRvdGFsX3NhZ2l0dGFsX2FyZWEgPC0gc3VtKGdyb3VwJHNhZ2l0dGFsX2FyZWEsIG5hLnJtID0gVFJVRSkNCiAgICANCiAgICAjIENhbGN1bGF0ZSBtZWFuIGFuZCBzdGFuZGFyZCBkZXZpYXRpb24gb2Ygc2FnaXR0YWwgYXJlYSBmb3IgdGhlIHN1YnNldCBvZiBwb29scyBpbiB0aGlzIGdyb3VwDQogICAgbWVhbl9zYWdpdHRhbF9hcmVhIDwtIG1lYW4oZ3JvdXAkc2FnaXR0YWxfYXJlYSwgbmEucm0gPSBUUlVFKQ0KICAgIHNkX3NhZ2l0dGFsX2FyZWEgPC0gc2QoZ3JvdXAkc2FnaXR0YWxfYXJlYSwgbmEucm0gPSBUUlVFKQ0KICAgIA0KICAgICMgQ2FsY3VsYXRlIG1lYW4gYW5kIHN0YW5kYXJkIGRldmlhdGlvbiBvZiBtYXhpbXVtIHJlc2lkdWFsIGRlcHRoIGZvciB0aGUgc3Vic2V0IG9mIHBvb2xzDQogICAgbWVhbl9tYXhfcmVzaWR1YWxfZGVwdGggPC0gbWVhbihncm91cCRtYXhfcmVzaWR1YWxfZGVwdGgsIG5hLnJtID0gVFJVRSkNCiAgICBzZF9tYXhfcmVzaWR1YWxfZGVwdGggPC0gc2QoZ3JvdXAkbWF4X3Jlc2lkdWFsX2RlcHRoLCBuYS5ybSA9IFRSVUUpDQogICAgDQogICAgIyBTdWJzZXQgdGhlIHJlc2lkdWFscy5kZiBmb3IgdGhlIGN1cnJlbnQgU2l0ZS1ZZWFyIGdyb3VwIHRvIGdldCB0aGUgdG90YWwgcmVhY2ggbGVuZ3RoDQogICAgZ3JvdXBfcmVzaWR1YWxzLmRmIDwtIHJlc2lkdWFscy5kZltyZXNpZHVhbHMuZGYkU2l0ZSA9PSBzaXRlICYgcmVzaWR1YWxzLmRmJHllYXIgPT0geWVhciwgXQ0KICAgIA0KICAgIGlmIChucm93KGdyb3VwX3Jlc2lkdWFscy5kZikgPT0gMCkgew0KICAgICAgd2FybmluZyhzcHJpbnRmKCJObyBtYXRjaGluZyByb3dzIGluIHJlc2lkdWFscy5kZiBmb3IgU2l0ZSAnJXMnIGFuZCBZZWFyICclcycuIiwgc2l0ZSwgeWVhcikpDQogICAgICBuZXh0DQogICAgfQ0KICAgIA0KICAgICMgQ2FsY3VsYXRlIHRoZSBwcm9wb3J0aW9uIG9mIHJlYWNoIGxlbmd0aCBpbiByZXNpZHVhbCBwb29scyBmb3IgdGhpcyBncm91cA0KICAgIHRvdGFsX3Bvb2xfbGVuZ3RoIDwtIHN1bShncm91cCRwb29sX2xlbmd0aCwgbmEucm0gPSBUUlVFKQ0KICAgIHRvdGFsX3JlYWNoX2xlbmd0aCA8LSBtYXgoZ3JvdXBfcmVzaWR1YWxzLmRmJGRpc3RhbmNlLCBuYS5ybSA9IFRSVUUpDQogICAgcHJvcG9ydGlvbl9sZW5ndGhfaW5fcmVzaWR1YWxfcG9vbCA8LSB0b3RhbF9wb29sX2xlbmd0aCAvIHRvdGFsX3JlYWNoX2xlbmd0aA0KICAgIA0KICAgICMgQ3JlYXRlIGEgc3VtbWFyeSB0YWJsZSBmb3IgdGhpcyBncm91cA0KICAgIHN1YnNldF9zdW1tYXJ5IDwtIGRhdGEuZnJhbWUoDQogICAgICBTaXRlID0gc2l0ZSwNCiAgICAgIFllYXIgPSB5ZWFyLA0KICAgICAgdG90YWxfc2FnaXR0YWxfYXJlYSA9IHRvdGFsX3NhZ2l0dGFsX2FyZWEsDQogICAgICBtZWFuX3NhZ2l0dGFsX2FyZWEgPSBtZWFuX3NhZ2l0dGFsX2FyZWEsDQogICAgICBzZF9zYWdpdHRhbF9hcmVhID0gc2Rfc2FnaXR0YWxfYXJlYSwNCiAgICAgIG1lYW5fbWF4X3Jlc2lkdWFsX2RlcHRoID0gbWVhbl9tYXhfcmVzaWR1YWxfZGVwdGgsDQogICAgICBzZF9tYXhfcmVzaWR1YWxfZGVwdGggPSBzZF9tYXhfcmVzaWR1YWxfZGVwdGgsDQogICAgICBwcm9wb3J0aW9uX2xlbmd0aF9pbl9yZXNpZHVhbF9wb29sID0gcHJvcG9ydGlvbl9sZW5ndGhfaW5fcmVzaWR1YWxfcG9vbA0KICAgICkNCiAgICANCiAgICAjIEFwcGVuZCB0aGUgc3VtbWFyeSBmb3IgdGhlIGN1cnJlbnQgU2l0ZS1ZZWFyIGNvbWJpbmF0aW9uIHRvIHRoZSBsaXN0DQogICAgc3Vic2V0X3N1bW1hcnlfbGlzdFtbZ3JvdXBfbmFtZV1dIDwtIHN1YnNldF9zdW1tYXJ5DQogIH0NCiAgDQogICMgQ29tYmluZSB0aGUgcmVzdWx0cyBmcm9tIGFsbCBTaXRlLVllYXIgZ3JvdXBzIGludG8gYSBzaW5nbGUgZGF0YWZyYW1lDQogIGZpbmFsX3N1YnNldF9zdW1tYXJ5X2RmIDwtIGRvLmNhbGwocmJpbmQsIHN1YnNldF9zdW1tYXJ5X2xpc3QpDQogIA0KICByZXR1cm4oZmluYWxfc3Vic2V0X3N1bW1hcnlfZGYpDQp9DQoNCnN1YnNldF9zdW1tYXJ5X3Jlc3VsdCA8LSBjYWxjdWxhdGVfc3Vic2V0X3N1bW1hcnkocG9vbF9zdW1tYXJ5X3Jlc3VsdCwgcmVzaWR1YWxzLmRmKQ0KDQojIERpc3BsYXkgdGhlIHJlc3VsdCBhcyBhIHRhYmxlDQpzdWJzZXRfc3VtbWFyeV9yZXN1bHQgPC0gc3Vic2V0X3N1bW1hcnlfcmVzdWx0ICU+JQ0KICBzZWxlY3QoU2l0ZSwgWWVhciwgZXZlcnl0aGluZygpKSAgIyBNb3ZlIFNpdGUgYW5kIFllYXIgdG8gdGhlIGxlZnQNCmRhdGF0YWJsZSgNCiAgc3Vic2V0X3N1bW1hcnlfcmVzdWx0LA0KICBjYXB0aW9uID0gIlJlYWNoIFN1bW1hcnkgU3RhdGlzdGljcyBmb3IgUG9vbHMgYnkgU2l0ZSBhbmQgWWVhciIsDQogIHJvd25hbWVzID0gRkFMU0UsICAjIEhpZGUgcm93IG51bWJlcnMNCiAgb3B0aW9ucyA9IGxpc3QoDQogICAgcGFnZUxlbmd0aCA9IDEwLCAgIyBOdW1iZXIgb2Ygcm93cyBwZXIgcGFnZQ0KICAgIGF1dG9XaWR0aCA9IFRSVUUNCiAgKQ0KKSU+JQ0KICBmb3JtYXRSb3VuZChjb2x1bW5zID0gbmFtZXMoc3Vic2V0X3N1bW1hcnlfcmVzdWx0KVtzYXBwbHkoc3Vic2V0X3N1bW1hcnlfcmVzdWx0LCBpcy5udW1lcmljKV0sIGRpZ2l0cyA9IDMpDQoNCiMgRXhwb3J0IHRhYmxlDQpleHBvcnRfdGFibGUoYXMuZGF0YS5mcmFtZShzdWJzZXRfc3VtbWFyeV9yZXN1bHQpLCAiUmVhY2ggU3VtbWFyeSBTdGF0cyBmb3IgUG9vbHMgYnkgU2l0ZSBhbmQgWWVhci5jc3YiKQ0KYGBgDQpUaGVzZSBhYm92ZSBzdGF0aXN0aWNzIHNob3VsZCBiZSB1c2VmdWwgZm9yIHRyYWNraW5nIGNoYW5nZXMgb3ZlciB0aW1lLCBvciBjb21wYXJpbmcgcmVmZXJlbmNlIC8gY29udHJvbCByZWFjaGVzLiBCZWNhdXNlIHRoZXkgYXJlIGFsbCBiYXNlZCBvbiByZXNpZHVhbCBkZXB0aHMsIHRoZXkgYXJlIGZsb3ctaW5kZXBlbmRlbnQuIA0KDQpUb3RhbCBzYWdpdHRhbCBhcmVhIGFuZCBwcm9wb3J0aW9uIG9mIHRoZSByZWFjaCBsZW5ndGggaW4gcmVzaWR1YWwgcG9vbCBzaG91bGQgYmUgY29tcGFyZWQgYmV0d2VlbiB5ZWFycyBhbmQvb3Igc2l0ZXMsIGFuZCB5b3UgY2FuIGludGVycHJldCB3aGV0aGVyIHRoZSBjaGFuZ2VzIGFyZSBpbiB0aGUgcHJlZGljdGVkIGRpcmVjdGlvbiBhbmQgb2YgYSBtZWFuaW5nZnVsIG1hZ25pdHVkZS4gU2luY2UgdGhlc2UgdHdvIG1ldHJpY3MgaGF2ZSBvbmUgdmFsdWUgcGVyIHJlYWNoLCB0aGUgbWV0cmljcyB0aGVtc2VsdmVzIGNhbm5vdCBiZSBldmFsdWF0ZWQgc3RhdGlzdGljYWxseSAodW5sZXNzIHlvdSBoYXZlIGEgbGFyZ2UgbnVtYmVyIG9mIHJlYWNoZXMveWVhcnMpLCBob3dldmVyIGEgZGlyZWN0aW9uYWwgY2hhbmdlIG92ZXIgdGltZSB0aGF0IGFsaWducyB3aXRoIHlvdXIgcHJlZGljdGlvbnMgaXMgb2J2aW91c2x5IHF1aXRlIGEgZ29vZCBzaWduLiANCg0KIyMgSW5mZXJlbnRpYWwgVGVzdHMNCg0KV2UgY2FuIGFwcGx5IGluZmVyZW50aWFsIHN0YXRpc3RpY2FsIHRlc3RzIHRvIHRoZSBzYWdpdHRhbCBhcmVhLCBtYXhpbXVtIHBvb2wgZGVwdGgsIGFuZCBwb29sIGxlbmd0aCBkYXRhIC0gdGhhdCBpcywgdGhlIGRhdGEgd2hpY2ggaGF2ZSB2YWx1ZXMgYXQgdGhlIGxldmVsIG9mIGVhY2ggcG9vbCAoaS5lLiwgYSBwb3B1bGF0aW9uIG9mIHZhbHVlcyBpcyBhdmFpbGFibGUgcGVyIHJlYWNoL3llYXIpLiBXZSB3aWxsIHVzZSBpbmZlcmVudGlhbCBzdGF0aXN0aWNhbCB0ZXN0cyB0byBkZXRlcm1pbmUgd2hldGhlciB0aGUgZGlmZmVyZW5jZXMgd2Ugb2JzZXJ2ZWQgYW1vbmcgcmVhY2hlcyBhbmQgeWVhcnMgYXJlIGxpa2VseSB0byBiZSBkdWUgdG8gY2hhbmNlLiBZb3Ugd2lsbCBiZSBmYW1pbGlhciB3aXRoIHAgdmFsdWVzIG9mIDAuMDUgKG9ic2VydmVkIHJlc3VsdCBleHBlY3RlZCBqdXN0IGR1ZSB0byBjaGFuY2UgMSBpbiAyMCB0aW1lcykgYW5kIHdlIHdpbGwgdXNlIHA9MC4wNSBhcyBvdXIgY3V0LW9mZiBoZXJlLiBIb3dldmVyLCBkZXBlbmRpbmcgb24geW91ciBhZGFwdGl2ZSBtYW5hZ2VtZW50IHBsYW5zLCB5b3UgbWF5IGJlIHdpbGxpbmcgdG8gYWNjZXB0IGRpZmZlcmVudCBsZXZlbHMgb2YgY2VydGFpbnR5LCBhbmQgcCB2YWx1ZXMgb2YgMC4xIGFyZSBub3QgdW5oZWFyZCBvZiBpbiByZXN0b3JhdGlvbiBwcm9qZWN0cy4gVGhpcyBhbGwgZGVwZW5kcyBvbiB0aGUgcmlzayB0b2xlcmFuY2Ugb2YgeW91IGFuZCB5b3VyIHRlYW0sIGFuZCBzaG91bGQgYmUgZXN0YWJsaXNoZWQgYmVmb3JlIGNvbmR1Y3RpbmcgYW5hbHlzZXMuDQoNCkZvciB0aGVzZSBpbmZlcmVudGlhbCB0ZXN0cyB3ZSB3aWxsIHVzZSBBTk9WQXMgYmVjYXVzZSBvZiB0aGVpciBmYW1pbGlhcml0eSBmb3IgZWNvbG9naXN0cyBhbmQgZXhwZWN0ZWQgc3VpdGFiaWxpdHkgZm9yIHRoZSBkYXRhLiBGb3IgdGhlIG1ldHJpY3MgcmVsYXRpbmcgdG8gcmVzaWR1YWwgcG9vbHMgdGhhdCB3ZSBoYXZlIGdlbmVyYXRlZCwgd2Ugd2lsbCB0ZXN0IGZvciBkaWZmZXJlbmNlcyBiZXR3ZWVuIHNpdGVzLCB5ZWFycywgYW5kIGFuIGludGVyYWN0aW9uIG9mIHNpdGVzKnllYXJzIChpLmUuLCBkaWQgdGhlIGRpZmZlcmVudCBsb2NhdGlvbnMgY2hhbmdlIGRpZmZlcmVudGx5IG92ZXIgdGltZSkuIFRoZSBjb2RlIHVzZXMgdGhlIHN1YnNldCBvZiBwb29scyB0aGF0IHdlcmUgZGVmaW5lZCBlYXJsaWVyIGFzICdtZWFuaW5nZnVsJy4NCg0KKipDaG9pY2Ugb2YgTWV0cmljKio6IEF0IHRoaXMgcG9pbnQsIHlvdSBzaG91bGQgY2hvb3NlIHdoaWNoIG9mICdzYWdpdHRhbCBhcmVhJywgJ21heGltdW0gcG9vbCBkZXB0aCcsIGFuZCAncG9vbCBsZW5ndGgnIGJlc3QgYWxpZ25zIHdpdGggeW91ciBuZWVkcyAoZS5nLiwgcmVsZXZhbmNlIHRvIHJlc3RvcmF0aW9uIG9iamVjdGl2ZSwgY29tcGFyaXNvbnMgd2l0aCBsaXRlcmF0dXJlLCBlYXNlIG9mIGNvbW11bmljYXRpb24pLiBZb3Ugd2lsbCBiYXNlIHlvdXIgaW50ZXJwcmV0YXRpb24gb2YgdGhlIEFOT1ZBIG9uIHRoaXMgY2hvc2VuIG1ldHJpYywgZXZlbiB0aG91Z2ggd2Ugd2lsbCBydW4gQU5PVkEgZm9yIGFsbCB0aHJlZS4gDQoNClRoZSByZWFzb24gZm9yIHNlbGVjdGluZyBvbmUgbWV0cmljIGZvciBpbnRlcnByZXRpbmcgeW91ciBoeXBvdGhlc2lzIGlzIHRoYXQgdGhlIG1ldHJpY3MgYXJlIG5vdCBpbmRlcGVuZGVudCBvZiBvbmUgYW5vdGhlcjogU2FnaXR0YWwgYXJlYSBpbmNvcnBvcmF0ZXMgZGVwdGggYW5kIGxlbmd0aCBjb21wb25lbnRzLCBhbmQgYWxsIHRocmVlIG1ldHJpY3MgYXJlIGNvbm5lY3RlZCBpbiB0aGUgc3RyZWFtOyBpZiB5b3UgdXNlZCBhIHN1YnNldCBvZiB0aGUgcmVzaWR1YWwgcG9vbHMsIGFsbCBtZXRyaWNzIGluaGVyZW50bHkgaW5jbHVkZSBzb21lIGluZm9ybWF0aW9uIGFib3V0IGRlcHRoLiBJZiB5b3Ugd2VyZSB0byBjb250aW51ZSB3aXRob3V0IGRlY2lkaW5nIHVwb24gYSBtZXRyaWMsIGl0IHdvdWxkIGJlIHRvbyB0ZW1wdGluZyB0byBjb21lIHVwIHdpdGggcG9zdC1ob2MgZXhwbGFuYXRpb25zIChlLmcuLCBpZiBzYWdpdHRhbCBhcmVhIGluY3JlYXNlZCBidXQgbm90IGRlcHRoIG9yIGxlbmd0aCkuIFlvdSBzaG91bGQgY2VydGFpbmx5IGNvbnNpZGVyIHBvdGVudGlhbCBpbXBsaWNhdGlvbnMgb2YgeW91ciByZXN1bHRzIChjYXJlZnVsbHkpLCBidXQgaW4gdGVybXMgb2YgZXZhbHVhdGluZyB0aGUgc3VjY2VzcyBvZiB5b3VyIHByb2plY3QsIGl0IGlzIGltcG9ydGFudCB0aGF0IHlvdSBkZWNpZGUgaW4gYWR2YW5jZSB3aGljaCBtZXRyaWMgY2hhbmdlID0gc3VjY2Vzcy4NCg0KQWx0aG91Z2ggaXQgbWF5IGJlIHBvc3NpYmxlIHRvIHJ1biBhIE1BTk9WQSB0ZXN0ICh3aGljaCBjYW4gYWNjb21tb2RhdGUgY29ycmVsYXRlZCBkZXBlbmRlbnQgdmFyaWFibGVzKSB1c2luZyBhbGwgdGhyZWUgbWV0cmljcyB0b2dldGhlciwgTUFOT1ZBIHRlc3RzIHR5cGljYWxseSByZXF1aXJlIGxhcmdlciBzYW1wbGUgc2l6ZXMgdGhhbiB3ZSBhbnRpY2lwYXRlIGZvciBtYW55IHJlYWNoIHN1cnZleXMuIFRoZXJlZm9yZSwgd2Ugc3RpY2sgd2l0aCBtdWx0aXBsZSBBTk9WQXMgd2l0aCBhIGxhcmdlIGRvc2Ugb2YgY2F1dGlvbi4NCg0KIyMjIEFzc3VtcHRpb24gUm9idXN0bmVzcw0KDQpXaGVuZXZlciBhcHBseWluZyBzdGF0aXN0aWNhbCB0ZXN0cywgd2Ugc2hvdWxkIGVuc3VyZSB0aGF0IG91ciBkYXRhIGlzIHN1aXRhYmxlLCBpbiB0aGF0IGl0IG1lZXRzIHRoZSBhc3N1bXB0aW9ucyBvZiB0aGUgaW50ZW5kZWQgaW5mZXJlbnRpYWwgdGVzdC4gRm9yIEFOT1ZBcyB0aGUgYXNzdW1wdGlvbnMgYXJlOg0KDQotIERhdGEgaW4gZGlmZmVyZW50IGdyb3VwcyBzaG91bGQgYmUgaW5kZXBlbmRlbnQ6IA0KDQogIC0gT25lIG9mIHlvdXIgc2l0ZXMgbXVzdCBub3QgY2F1c2UgY2hhbmdlcyBpbiBhbm90aGVyICh0aG91Z2ggYm90aCBzaXRlcyBleHBlcmllbmNpbmcgc2hhcmVkICdleHRlcm5hbCcgY2F1c2FsIGZhY3RvcnMsIHN1Y2ggYXMgYmVpbmcgaW4gdGhlIHNhbWUgd2F0ZXJzaGVkLCBpcyBhY2NlcHRhYmxlKS4gVGhpcyBpcyBob3BlZnVsbHkgYWNjb3VudGVkIGZvciBieSBnb29kIHNlbGVjdGlvbiBvZiBpbXBhY3QvY29udHJvbC9yZWZlcmVuY2Ugc2l0ZXMuIA0KICANCiAgLSBZb3UgbWF5IG5vdGUgdGhhdCBubyBzaXRlIGlzIGFjdHVhbGx5IGluZGVwZW5kZW50IGZyb20gdGhhdCBzYW1lIHNpdGUgaW4gdGhlIHBhc3QuIEZvciBsb25nZXIgdGltZS1zZXJpZXMgd2Ugd291bGQgbmVlZCB0byBhZG9wdCBhIGRpZmZlcmVudCBpbmZlcmVudGlhbCBhcHByb2FjaCB0byBhdm9pZCBhdXRvY29ycmVsYXRpb24sIGJ1dCBoZXJlIHdlIGFyZSBkZWFsaW5nIHdpdGggc2ltcGxlIGJlZm9yZSB2cyBhZnRlciBjb21wYXJpc29ucywgYW5kIGl0IGlzIHdpZGVseSBhY2NlcHRlZCB0aGF0IEFOT1ZBcyBhcmUgc3VpdGFibGUgZm9yIGJlZm9yZS9hZnRlciBjb21wYXJpc29ucyBpZiB0aGUgY29tcGFyaXNvbiBpcyBiYWxhbmNlZCAoZS5nLiwgMiB5ZWFycyBvZiBiZWZvcmUgZGF0YSBjb21wYXJlZCB3aXRoIDIgeWVhcnMgb2YgYWZ0ZXIgZGF0YSkuDQogIA0KLSBSZXNpZHVhbHMgYXJlIG5vcm1hbGx5IGRpc3RyaWJ1dGVkOiBJbiB0aGlzIGNhc2Ugd2UgbWVhbiByZXNpZHVhbHMgbW9yZSBicm9hZGx5IC0gdGhlIGRpZmZlcmVuY2UgYmV0d2VlbiBlYWNoIGRhdGFwb2ludCBhbmQgdGhlIG1lYW4uIFdlIHdpbGwgZXhhbWluZSB0aGlzIGFzc3VtcHRpb24gdXNpbmcgUS1RIHBsb3RzIGFuZCB0aGUgU2hhcGlyby1XaWxrIG5vcm1hbGl0eSB0ZXN0Lg0KDQotIEhvbW9zY2VkYXN0aWNpdHk6IFZhcmlhbmNlIHNob3VsZCBiZSBicm9hZGx5IGVxdWFsIGFjcm9zcyBhbGwgZ3JvdXBzLiBXZSB3aWxsIHRlc3QgdGhpcyB3aXRoIExldmVuZSdzIHRlc3QuDQoNCklmIGFueSBvZiB0aGVzZSBhc3N1bXB0aW9ucyBhcmUgdmlvbGF0ZWQsIHdlIGNhbiB0cmFuc2Zvcm0gdGhlIGRhdGEgYW5kIHRlc3Qgd2hldGhlciB0aGUgdHJhbnNmb3JtZWQgZGF0YSAobG9nLSwgYXJjc2luZS0gZXRjLikgc2F0aXNmaWVzIHRoZSBhc3N1bXB0aW9ucy4gSWYgdGhpcyBpcyBub3QgYW4gb3B0aW9uLCB3ZSBzaG91bGQgc2VlayBhIG1vcmUgc3VpdGFibGUgc3RhdGlzdGljYWwgdGVzdCAoZS5nLiBXZWxjaCdzIEFOT1ZBIG9yIG1peGVkLWVmZmVjdHMgbW9kZWxzKS4gDQoNClRoZSB0ZXN0cyBvZiBhc3N1bXB0aW9ucyBhcmUgY2FycmllZCBvdXQgYmVsb3csIGFmdGVyIHdlIHNwZWNpZnkgdGhlIGJlZm9yZSBhbmQgYWZ0ZXIgZGF0YSB0aGF0IHlvdSB3aXNoIHRvIGNvbXBhcmUuDQoNCiMjIyMgQmVmb3JlIC8gQWZ0ZXIgWWVhcnMNCg0KRW50ZXIgeW91ciBiZWZvcmUgYW5kIGFmdGVyIHllYXJzIGluIHRoZSBiZWxvdyBjb2RlLCB5b3UgbWF5IGhhdmUgbW9yZSB0aGFuIG9uZSB5ZWFyIGluIGVhY2ggY2F0ZWdvcnkuIFJlbWVtYmVyIHRoYXQgdGhlc2Ugc2hvdWxkIGJhbGFuY2UgKGVxdWFsIG51bWJlciBvZiB5ZWFycyBiZWZvcmUgYXMgYWZ0ZXIpLCBidXQgdGhleSBuZWVkIG5vdCBiZSBjb25zZWN1dGl2ZSB5ZWFycy4gSWYgeW91IGRvIG5vdCBoYXZlIGJhbGFuY2VkIGRhdGEgKGUuZy4sIG9ubHkgb25lIHllYXIgd2FzIHBvc3NpYmxlIGJlZm9yZSBwcm9qZWN0IGltcGxlbWVudGF0aW9uKSBiZSB2ZXJ5IGNhdXRpb3VzIGluIHJ1bm5pbmcgYW5kIGludGVycHJldGluZyBhbiBBTk9WQS4gWW91IGNvdWxkIHNlbGVjdCBvbmx5IGEgc3Vic2V0IG9mIHlvdXIgZGF0YSB0byBrZWVwIHRoZSBjb21wYXJpc29uIGJhbGFuY2VkLCBidXQgaWYgeW91IGRvIHRoaXMgZm9yIG1vcmUgdGhhbiBvbmUgc2V0IG9mIGRhdGVzIHlvdSBtdXN0IGFjY291bnQgZm9yIHRoZSBtdWx0aXBsZSBjb21wYXJpc29ucyBpbmZsYXRpbmcgdGhlIGxpa2VsaWhvb2Qgb2YgYSBUeXBlIEkgZXJyb3IgKGZhbHNlIHBvc2l0aXZlKS4NCg0KYGBge3IgZGVmaW5lIGJlZm9yZSBhZnRlcn0NCiMgRGVmaW5lICJCZWZvcmUiIGFuZCAiQWZ0ZXIiIHllYXJzDQpiZWZvcmVfeWVhcnMgPC0gYygyMDI0KSAjYWRkIG1vcmUgeWVhcnMgaW5zaWRlIGJyYWNrZXRzIGlmIG5lZWRlZCwgZS5nLiAnYygyMDI0LCAyMDI1LCAyMDI2KScNCmFmdGVyX3llYXJzIDwtIGMoMjAyNSkgI2FkZCBtb3JlIHllYXJzIGluc2lkZSBicmFja2V0cyBpZiBuZWVkZWQsIGUuZy4gJ2MoMjAyNywgMjAyOSwgMjAzNiknDQpgYGANCg0KYGBge3IgY2F0ZWdvcmlzZSBieSBiZWZvcmUgYWZ0ZXIsIGVjaG8gPSBGQUxTRX0NCiMgQ2F0ZWdvcml6ZSB5ZWFycw0KcG9vbF9zdW1tYXJ5X3Jlc3VsdCA8LSBwb29sX3N1bW1hcnlfcmVzdWx0ICU+JQ0KICBtdXRhdGUoVGltZV9DYXRlZ29yeSA9IGNhc2Vfd2hlbigNCiAgICB5ZWFyICVpbiUgYmVmb3JlX3llYXJzIH4gIkJlZm9yZSIsDQogICAgeWVhciAlaW4lIGFmdGVyX3llYXJzIH4gIkFmdGVyIiwNCiAgICBUUlVFIH4gTkFfY2hhcmFjdGVyXw0KICApKQ0KYGBgDQoNClRoZSBuZXh0IHNlY3Rpb24gb2YgY29kZSBnZW5lcmF0ZXMgdGVzdHMgYW5kIGZpZ3VyZXMgdGhhdCB5b3Ugc2hvdWxkIHJldmlldyB0byBlbnN1cmUgeW91ciBkYXRhIGFyZSBzdWl0YWJsZSBmb3IgYW4gQU5PVkEuIEluIGJyaWVmLCBsb29rIGZvciB0aGUgZm9sbG93aW5nOg0KDQotIEJveHBsb3RzOiBjb25zaWRlciB3aGV0aGVyIG91dGxpZXJzIChkb3RzKSBhcmUgcmVhbCBvciBlcnJvcnMNCi0gUS1RIHBsb3RzOiBhIHJlYXNvbmFibHkgc3RyYWlnaHQgbGluZSBvZiBwb2ludHMgbWVhbnMgYWxpZ25tZW50IHdpdGggbm9ybWFsIGRpc3RyaWJ1dGlvbg0KLSBOb3JtYWxpdHkgdGVzdCAoU2hhcGlyby1XaWxrKTogcDwwLjA1IGluZGljYXRlcyBub24tbm9ybWFsaXR5DQotIExldmVuZSdzIHRlc3Q6IHA8MC4wNSBpbmRpY2F0ZXMgdGhhdCB2YXJpYW5jZSBhbW9uZyBncm91cHMgZGlmZmVycw0KLSBTa2V3bmVzcyB2YWx1ZXMgPCAwIGFyZSBsZWZ0IHNrZXdlZCwgPiAwIHJpZ2h0IHNrZXdlZC4gS3VydG9zaXMgdmFsdWVzIDwgMyBsaWdodC10YWlsZWQsID4gMyBoZWF2eS10YWlsZWQuDQoNCmBgYHtyIG5vcm1hbGl0eSBhc3N1bXB0aW9ucyBldGMsIGVjaG8gPSBGQUxTRX0NCiMgRmlsdGVyIG91dCBzaXRlcyB3aXRob3V0IGJvdGggdGltZSBjYXRlZ29yaWVzLiBSZW1vdmUgcm93cyB3aXRoIHBvb2xfaWQgPSAiVG90YWwiLiANCnBvb2xfc3VtbWFyeV9maWx0ZXJlZCA8LSBwb29sX3N1bW1hcnlfcmVzdWx0ICU+JQ0KICBmaWx0ZXIocG9vbF9pZCAhPSAiVG90YWwiKSAlPiUNCiAgZ3JvdXBfYnkoU2l0ZSkgJT4lDQogIGZpbHRlcihhbGwoYygiQmVmb3JlIiwgIkFmdGVyIikgJWluJSBUaW1lX0NhdGVnb3J5KSkgJT4lDQogIHVuZ3JvdXAoKQ0KDQojIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIEZ1bmN0aW9uIHRvIGdlbmVyYXRlIGJveHBsb3RzLiBMb29rIG91dCBmb3Igb3V0bGllcnMNCmdlbmVyYXRlX2JveHBsb3RzIDwtIGZ1bmN0aW9uKHBvb2xfc3VtbWFyeV9kZikgew0KICB2YXJpYWJsZXMgPC0gYygic2FnaXR0YWxfYXJlYSIsICJtYXhfcmVzaWR1YWxfZGVwdGgiLCAicG9vbF9sZW5ndGgiKQ0KICBib3hwbG90c19saXN0IDwtIGxpc3QoKQ0KICANCiAgZm9yICh2YXIgaW4gdmFyaWFibGVzKSB7DQogICAgYm94cGxvdCA8LSBnZ3Bsb3QocG9vbF9zdW1tYXJ5X2RmLCBhZXMoeCA9IGludGVyYWN0aW9uKFNpdGUsIFRpbWVfQ2F0ZWdvcnkpLCB5ID0gLmRhdGFbW3Zhcl1dKSkgKw0KICAgICAgZ2VvbV9ib3hwbG90KCkgKw0KICAgICAgbGFicyh0aXRsZSA9IHBhc3RlKCJCb3hwbG90IG9mIiwgdmFyKSwgeCA9ICJTaXRlLVRpbWUgQ2F0ZWdvcnkiLCB5ID0gdmFyKSArDQogICAgICB0aGVtZShheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDQ1LCBoanVzdCA9IDEpKQ0KICAgIGJveHBsb3RzX2xpc3RbW3Zhcl1dIDwtIGJveHBsb3QNCiAgfQ0KICByZXR1cm4oYm94cGxvdHNfbGlzdCkNCn0NCg0KIyBHZW5lcmF0ZSBib3hwbG90cw0KYm94cGxvdHMgPC0gZ2VuZXJhdGVfYm94cGxvdHMocG9vbF9zdW1tYXJ5X2ZpbHRlcmVkKQ0KDQojIERpc3BsYXkgYm94cGxvdHMNCmZvciAocGxvdCBpbiBib3hwbG90cykgew0KICBwcmludChwbG90KQ0KfSAjIExvb2sgb3V0IGZvciBvdXRsaWVycw0KDQojIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyBGdW5jdGlvbiB0byBnZW5lcmF0ZSBRLVEgcGxvdHMuIExvb2sgZm9yIGRldmlhdGlvbnMgZnJvbSBsaW5lYXJpdHkNCmdlbmVyYXRlX3FxcGxvdHMgPC0gZnVuY3Rpb24ocG9vbF9zdW1tYXJ5X2RmKSB7DQogICMgQ3JlYXRlIGEgbGlzdCBvZiB2YXJpYWJsZXMgdG8gcGxvdA0KICB2YXJpYWJsZXMgPC0gYygic2FnaXR0YWxfYXJlYSIsICJtYXhfcmVzaWR1YWxfZGVwdGgiLCAicG9vbF9sZW5ndGgiKQ0KICANCiAgIyBJbml0aWFsaXplIGEgbGlzdCB0byBzdG9yZSB0aGUgUS1RIHBsb3RzDQogIHFxcGxvdHNfbGlzdCA8LSBsaXN0KCkNCiAgDQogICMgSXRlcmF0ZSBvdmVyIGVhY2ggdmFyaWFibGUNCiAgZm9yICh2YXIgaW4gdmFyaWFibGVzKSB7DQogICAgcXFwbG90IDwtIGdncGxvdChwb29sX3N1bW1hcnlfZGYsIGFlcyhzYW1wbGUgPSAuZGF0YVtbdmFyXV0pKSArICANCiAgICAgIHN0YXRfcXEoKSArDQogICAgICBzdGF0X3FxX2xpbmUoKSArDQogICAgICBsYWJzKHRpdGxlID0gcGFzdGUoIlEtUSBQbG90IG9mIiwgdmFyKSkgKw0KICAgICAgZmFjZXRfd3JhcCh+IGludGVyYWN0aW9uKFNpdGUsIHllYXIpKQ0KICAgIA0KICAgICMgQWRkIHRoZSBwbG90IHRvIHRoZSBsaXN0DQogICAgcXFwbG90c19saXN0W1t2YXJdXSA8LSBxcXBsb3QNCiAgfQ0KICANCiAgIyBSZXR1cm4gdGhlIGxpc3Qgb2YgUS1RIHBsb3RzDQogIHJldHVybihxcXBsb3RzX2xpc3QpDQp9DQoNCiMgR2VuZXJhdGUgUS1RIHBsb3RzDQpxcXBsb3RzIDwtIGdlbmVyYXRlX3FxcGxvdHMocG9vbF9zdW1tYXJ5X2ZpbHRlcmVkKQ0KDQojIERpc3BsYXkgUS1RIHBsb3RzDQpmb3IgKHBsb3QgaW4gcXFwbG90cykgew0KICBwcmludChwbG90KQ0KfSAgIyBMb29rIGZvciBkZXZpYXRpb25zIGZyb20gbGluZWFyaXR5DQoNCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIEZ1bmN0aW9uIHRvIHRlc3QgZm9yIG5vcm1hbGl0eSANCnRlc3Rfbm9ybWFsaXR5IDwtIGZ1bmN0aW9uKHBvb2xfc3VtbWFyeV9kZikgew0KICBwb29sX3N1bW1hcnlfZ3JvdXBlZCA8LSBzcGxpdChwb29sX3N1bW1hcnlfZGYsIGxpc3QocG9vbF9zdW1tYXJ5X2RmJFNpdGUsIHBvb2xfc3VtbWFyeV9kZiRUaW1lX0NhdGVnb3J5KSkNCiAgbm9ybWFsaXR5X3Jlc3VsdHNfbGlzdCA8LSBsaXN0KCkNCiAgDQogIGZvciAoZ3JvdXBfbmFtZSBpbiBuYW1lcyhwb29sX3N1bW1hcnlfZ3JvdXBlZCkpIHsNCiAgICBncm91cCA8LSBwb29sX3N1bW1hcnlfZ3JvdXBlZFtbZ3JvdXBfbmFtZV1dDQogICAgaWYgKG5yb3coZ3JvdXApIDwgMykgew0KICAgICAgbm9ybWFsaXR5X3Jlc3VsdHNfbGlzdFtbZ3JvdXBfbmFtZV1dIDwtIGRhdGEuZnJhbWUoDQogICAgICAgIFNpdGUgPSBOQSwgVGltZV9DYXRlZ29yeSA9IE5BLA0KICAgICAgICBtYXhfcmVzaWR1YWxfZGVwdGhfcF92YWx1ZSA9IE5BLA0KICAgICAgICBzYWdpdHRhbF9hcmVhX3BfdmFsdWUgPSBOQSwNCiAgICAgICAgcG9vbF9sZW5ndGhfcF92YWx1ZSA9IE5BLA0KICAgICAgICBtZXNzYWdlID0gIk5vdCBlbm91Z2ggZGF0YSBmb3Igbm9ybWFsaXR5IHRlc3QiDQogICAgICApDQogICAgICBuZXh0DQogICAgfQ0KICAgIG1heF9yZXNpZHVhbF9kZXB0aF90ZXN0IDwtIHNoYXBpcm8udGVzdChncm91cCRtYXhfcmVzaWR1YWxfZGVwdGgpDQogICAgc2FnaXR0YWxfYXJlYV90ZXN0IDwtIHNoYXBpcm8udGVzdChncm91cCRzYWdpdHRhbF9hcmVhKQ0KICAgIHBvb2xfbGVuZ3RoX3Rlc3QgPC0gc2hhcGlyby50ZXN0KGdyb3VwJHBvb2xfbGVuZ3RoKQ0KICAgIA0KICAgIG5vcm1hbGl0eV9yZXN1bHRzX2xpc3RbW2dyb3VwX25hbWVdXSA8LSBkYXRhLmZyYW1lKA0KICAgICAgU2l0ZSA9IHVuaXF1ZShncm91cCRTaXRlKSwNCiAgICAgIFRpbWVfQ2F0ZWdvcnkgPSB1bmlxdWUoZ3JvdXAkVGltZV9DYXRlZ29yeSksDQogICAgICBtYXhfcmVzaWR1YWxfZGVwdGhfcF92YWx1ZSA9IG1heF9yZXNpZHVhbF9kZXB0aF90ZXN0JHAudmFsdWUsDQogICAgICBzYWdpdHRhbF9hcmVhX3BfdmFsdWUgPSBzYWdpdHRhbF9hcmVhX3Rlc3QkcC52YWx1ZSwNCiAgICAgIHBvb2xfbGVuZ3RoX3BfdmFsdWUgPSBwb29sX2xlbmd0aF90ZXN0JHAudmFsdWUsDQogICAgICBtZXNzYWdlID0gIk5vcm1hbGl0eSB0ZXN0IGNvbXBsZXRlZCINCiAgICApDQogIH0NCiAgbm9ybWFsaXR5X3Jlc3VsdHNfZGYgPC0gZG8uY2FsbChyYmluZCwgbm9ybWFsaXR5X3Jlc3VsdHNfbGlzdCkNCiAgcmV0dXJuKG5vcm1hbGl0eV9yZXN1bHRzX2RmKQ0KfQ0KDQpub3JtYWxpdHlfcmVzdWx0cyA8LSB0ZXN0X25vcm1hbGl0eShwb29sX3N1bW1hcnlfZmlsdGVyZWQpDQoNCm5vcm1hbGl0eV9yZXN1bHRzICU+JQ0KICBtdXRhdGUoDQogICAgbWF4X3Jlc2lkdWFsX2RlcHRoX3BfdmFsdWUgPSByb3VuZChtYXhfcmVzaWR1YWxfZGVwdGhfcF92YWx1ZSwgMyksDQogICAgc2FnaXR0YWxfYXJlYV9wX3ZhbHVlID0gcm91bmQoc2FnaXR0YWxfYXJlYV9wX3ZhbHVlLCAzKSwNCiAgICBwb29sX2xlbmd0aF9wX3ZhbHVlID0gcm91bmQocG9vbF9sZW5ndGhfcF92YWx1ZSwgMykNCiAgKSAlPiUNCiAga2FibGUoDQogICAgY2FwdGlvbiA9ICJOb3JtYWxpdHkgVGVzdCBSZXN1bHRzIGZvciBQb29sIFN1bW1hcnkgRGF0YSIsDQogICAgY29sLm5hbWVzID0gYygiU2l0ZSIsICJUaW1lIENhdGVnb3J5IiwgDQogICAgICAgICAgICAgICAgICAiTWF4IFJlc2lkdWFsIERlcHRoIFAtVmFsdWUiLCANCiAgICAgICAgICAgICAgICAgICJTYWdpdHRhbCBBcmVhIFAtVmFsdWUiLCANCiAgICAgICAgICAgICAgICAgICJQb29sIExlbmd0aCBQLVZhbHVlIiwgDQogICAgICAgICAgICAgICAgICAiTWVzc2FnZSIpLA0KICAgIGFsaWduID0gImMiLCAgIyBDZW50ZXItYWxpZ24gdGhlIGNvbHVtbnMNCiAgICByb3cubmFtZXMgPSBGQUxTRQ0KICApICMgbG9vayBvdXQgZm9yIHAgdmFsdWVzIDwwLjA1IHdoaWNoIGluZGljYXRlIG5vbi1ub3JtYWxpdHkNCg0KDQojIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIEZ1bmN0aW9uIHRvIHJ1biBMZXZlbmUncyBUZXN0IGZvciBlYWNoIHZhcmlhYmxlDQpydW5fbGV2ZW5lc190ZXN0IDwtIGZ1bmN0aW9uKHBvb2xfc3VtbWFyeV9kZikgew0KICAjIENyZWF0ZSBhIGxpc3Qgb2YgdmFyaWFibGVzIHRvIHRlc3QNCiAgdmFyaWFibGVzIDwtIGMoInNhZ2l0dGFsX2FyZWEiLCAibWF4X3Jlc2lkdWFsX2RlcHRoIiwgInBvb2xfbGVuZ3RoIikNCiAgDQogICMgSW5pdGlhbGl6ZSBhIGxpc3QgdG8gc3RvcmUgTGV2ZW5lJ3MgdGVzdCByZXN1bHRzDQogIGxldmVuZV9yZXN1bHRzX2xpc3QgPC0gbGlzdCgpDQogIA0KICAjIEl0ZXJhdGUgb3ZlciBlYWNoIHZhcmlhYmxlDQogIGZvciAodmFyIGluIHZhcmlhYmxlcykgew0KICAgIGxldmVuZV90ZXN0IDwtIGxldmVuZVRlc3QoYXMuZm9ybXVsYShwYXN0ZSh2YXIsICJ+IGludGVyYWN0aW9uKFNpdGUsIHllYXIpIiwgc2VwID0gIiIpKSwgZGF0YSA9IHBvb2xfc3VtbWFyeV9kZikNCiAgICANCiAgICAjIFN0b3JlIHRoZSByZXN1bHRzIGluIHRoZSBsaXN0DQogICAgbGV2ZW5lX3Jlc3VsdHNfbGlzdFtbdmFyXV0gPC0gbGV2ZW5lX3Rlc3QNCiAgfQ0KICANCiAgIyBSZXR1cm4gdGhlIGxpc3Qgb2YgTGV2ZW5lJ3MgdGVzdCByZXN1bHRzDQogIHJldHVybihsZXZlbmVfcmVzdWx0c19saXN0KQ0KfQ0KDQojIFJ1biBMZXZlbmUncyB0ZXN0DQpsZXZlbmVfcmVzdWx0cyA8LSBydW5fbGV2ZW5lc190ZXN0KHBvb2xfc3VtbWFyeV9maWx0ZXJlZCkNCg0KIyBEaXNwbGF5IExldmVuZSdzIHRlc3QgcmVzdWx0cyB3aXRoIHZhcmlhYmxlIG5hbWVzDQpmb3IgKHZhcl9uYW1lIGluIG5hbWVzKGxldmVuZV9yZXN1bHRzKSkgew0KICBjYXQoIlxuLS0tIExldmVuZSdzIFRlc3QgUmVzdWx0cyBmb3IiLCB2YXJfbmFtZSwgIi0tLVxuIikNCiAgcHJpbnQobGV2ZW5lX3Jlc3VsdHNbW3Zhcl9uYW1lXV0pDQp9ICMgSWYgcCA8IDAuMDUgdGhlbiB2YXJpYW5jZSAqaXMqIGRpZmZlcmVudCBhbW9uZyBncm91cHMgDQoNCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMgRnVuY3Rpb24gdG8gY2FsY3VsYXRlIHNrZXduZXNzIGFuZCBrdXJ0b3Npcw0KY2FsY3VsYXRlX3NrZXdfa3VydCA8LSBmdW5jdGlvbihwb29sX3N1bW1hcnlfZGYpIHsNCiAgIyBDcmVhdGUgYSBsaXN0IG9mIHZhcmlhYmxlcyB0byBhbmFseXplDQogIHZhcmlhYmxlcyA8LSBjKCJzYWdpdHRhbF9hcmVhIiwgIm1heF9yZXNpZHVhbF9kZXB0aCIsICJwb29sX2xlbmd0aCIpDQogIA0KICAjIEluaXRpYWxpemUgYSBsaXN0IHRvIHN0b3JlIHRoZSByZXN1bHRzDQogIHNrZXdfa3VydF9saXN0IDwtIGxpc3QoKQ0KICANCiAgIyBJdGVyYXRlIG92ZXIgZWFjaCB2YXJpYWJsZQ0KICBmb3IgKHZhciBpbiB2YXJpYWJsZXMpIHsNCiAgICBza2V3IDwtIHNrZXduZXNzKHBvb2xfc3VtbWFyeV9kZltbdmFyXV0sIG5hLnJtID0gVFJVRSkNCiAgICBrdXJ0IDwtIGt1cnRvc2lzKHBvb2xfc3VtbWFyeV9kZltbdmFyXV0sIG5hLnJtID0gVFJVRSkNCiAgICANCiAgICAjIFN0b3JlIHRoZSByZXN1bHRzDQogICAgc2tld19rdXJ0X2xpc3RbW3Zhcl1dIDwtIGRhdGEuZnJhbWUoDQogICAgICBWYXJpYWJsZSA9IHZhciwNCiAgICAgIFNrZXduZXNzID0gc2tldywNCiAgICAgIEt1cnRvc2lzID0ga3VydA0KICAgICkNCiAgfQ0KICANCiAgIyBDb21iaW5lIHRoZSByZXN1bHRzIGludG8gYSBzaW5nbGUgZGF0YWZyYW1lDQogIHNrZXdfa3VydF9kZiA8LSBkby5jYWxsKHJiaW5kLCBza2V3X2t1cnRfbGlzdCkNCiAgDQogIHJldHVybihza2V3X2t1cnRfZGYpDQp9DQoNCiMgQ2FsY3VsYXRlIHNrZXduZXNzIGFuZCBrdXJ0b3Npcw0Kc2tld19rdXJ0X3Jlc3VsdCA8LSBjYWxjdWxhdGVfc2tld19rdXJ0KHBvb2xfc3VtbWFyeV9maWx0ZXJlZCkNCg0KIyBEaXNwbGF5IHNrZXduZXNzIGFuZCBrdXJ0b3NpcyByZXN1bHRzDQpwcmludChza2V3X2t1cnRfcmVzdWx0KQ0KYGBgDQoNCklmLCBiYXNlZCBvbiB0aGUgYWJvdmUgZXZhbHVhdGlvbiwgeW91ciBkYXRhIGFwcGVhciB0byBiZSB1bnN1aXRhYmxlIGZvciB0aGUgaW50ZW5kZWQgaW5mZXJlbnRpYWwgdGVzdCB5b3UgbWF5IHdpc2ggdG8gdXNlIGFuIGFsdGVybmF0aXZlIG5vbi1wYXJhbWV0cmljIHRlc3Qgb3IgdHJhbnNmb3JtIHRoZSBkYXRhLiBXZSBwcm92aWRlIHNvbWUgYXNzaXN0YW5jZSBmb3IgdHJhbnNmb3JtYXRpb25zIGhlcmUsIGJ1dCB0aGlzIHBhcnQgbWF5IHJlcXVpcmUgc29tZSBtb3JlIHdvcmsgb24geW91ciBwYXJ0IHNpbmNlIHdlIGNhbm5vdCBwcmVkaWN0IHdoYXQgeW91ciBkYXRhIHdpbGwgbmVlZC4NCg0KQXMgYW4gZXhhbXBsZSwgb3VyIGRhdGEgYXBwZWFyZWQgbm9ybWFsbHkgZGlzdHJpYnV0ZWQgKHA+MC4wNSBTaGFwaXJvLVdpbGspIGJ1dCBMZXZlbmUncyB0ZXN0IHJldmVhbGVkIHRoYXQgc2FnaXR0YWwgYXJlYSB2YXJpYW5jZSB3YXMgdW5lcXVhbCBhY3Jvc3Mgc2l0ZS15ZWFycyAocDwwLjA1KS4gV2UgdGhlcmVmb3JlIGxvZy10cmFuc2Zvcm1lZCB0aGUgc2FnaXR0YWwgYXJlYSBkYXRhIGFuZCByZS1yYW4gdGhlIGFib3ZlIGRpYWdub3N0aWNzLCB3aXRoIExldmVuZSdzIHRlc3QgcmV0dXJuZWQgYXMgbm9uLXNpZ25pZmljYW50IGFuZCB0aGVyZWZvcmUgYWNjZXB0YWJsZSB0byBiZSB1c2VkIGluIEFOT1ZBcy4gTm90ZSB0aGF0IG9ubHkgdGhvc2UgbWV0cmljcyB0aGF0IGRvIG5vdCBtZWV0IHRoZSBhc3N1bXB0aW9ucyBuZWVkIHRvIGJlIHRyYW5zZm9ybWVkLg0KDQpUaGUgY29kZSB3ZSB1c2VkIGZvciB0aGUgdHJhbnNmb3JtYXRpb24gaXMgYmVsb3cuIElmIHlvdSBuZWVkIHRvIHRyYW5zZm9ybSB0aGUgZGF0YSwgZm9sbG93IHRoZXNlIHN0ZXBzOg0KDQojIyMgVHJhbnNmb3JtYXRpb25zDQoNCjEuIEFkZCB5b3VyIHRyYW5zZm9ybWF0aW9uKHMpIHRvIHRoZSBjb2RlIGNodW5rIGJlbG93LiBZb3UgbXVzdCBhZGQgYSBmb3JtdWxhIHRvIGNhbGN1bGF0ZSBhbiBhcHByb3ByaWF0ZSB0cmFuc2Zvcm1hdGlvbiBmb3IgZWFjaCBhcHBsaWNhYmxlIHZhcmlhYmxlIHdpdGhpbiAqdHJhbnNmb3JtYXRpb25zIDwtIGxpc3QoLi4uKSopLiBBcyBhbiBleGFtcGxlLCBpZiB5b3Ugd2FudCB0byB0cnkgYSBsb2cgdHJhbnNmb3JtYXRpb24sIHJlcGxhY2UgJ2lkZW50aXR5LCcgaW4gdGhlIGJlbG93IGNvZGUgd2l0aCAnZnVuY3Rpb24oeCkgaWZlbHNlKHggPiAwLCBsb2coeCksIE5BKSwnDQoNCjIuIFJlLXJ1biB0aGUgYWJvdmUgZGlhZ25vc3RpY3MgY29kZSBhZnRlciB1cGRhdGluZyB0aGUgYXBwbGljYWJsZSB2YXJpYWJsZSBuYW1lKHMpIGZvciBlYWNoIGRpYWdub3N0aWMgdGVzdDogd2hlcmUgaXQgc2F5cyAnKnZhcmlhYmxlcyA8LSBjKCJzYWdpdHRhbF9hcmVhIiwgIm1heF9yZXNpZHVhbF9kZXB0aCIsICJwb29sX2xlbmd0aCIpKicgeW91IHdpbGwgdXBkYXRlIGVhY2ggYXBwbGljYWJsZSB0cmFuc2Zvcm1lZCB2YXJpYWJsZSBuYW1lKHMpIHRvICIqdHJhbnNmb3JtZWRfKnZhcmlhYmxlX25hbWUiDQoNCjMuIE9uY2UgeW91IGhhdmUgYSB0cmFuc2Zvcm1lZCB2YXJpYWJsZSB0aGF0IG1lZXRzIHRoZSBhc3N1bXB0aW9ucyBvZiB0aGUgQU5PVkEsIHVwZGF0ZSB0aGUgQU5PVkEgaW5mZXJlbnRpYWwgdGVzdCBjb2RlIChpbiB0aGUgc3Vic2VxdWVudCBjb2RlIGNodW5rKSB0byB1c2UgdGhlICIqdHJhbnNmb3JtZWRfKnZhcmlhYmxlX25hbWUiDQoNCmBgYHtyIHRyYW5zZm9ybWF0aW9uc30NCiMgRnVuY3Rpb24gdG8gYXBwbHkgdHJhbnNmb3JtYXRpb25zIGFuZCBhcHBlbmQgdG8gdGhlIGRhdGFmcmFtZQ0KYXBwbHlfdHJhbnNmb3JtYXRpb25zIDwtIGZ1bmN0aW9uKGRhdGEsIHRyYW5zZm9ybWF0aW9ucykgew0KICBmb3IgKHZhciBpbiBuYW1lcyh0cmFuc2Zvcm1hdGlvbnMpKSB7DQogICAgdHJhbnNmb3JtX2ZuIDwtIHRyYW5zZm9ybWF0aW9uc1tbdmFyXV0NCiAgICB0cmFuc2Zvcm1lZF92YXIgPC0gcGFzdGUwKCJ0cmFuc2Zvcm1lZF8iLCB2YXIpDQogICAgIyBBcHBseSB0aGUgdHJhbnNmb3JtYXRpb24gYW5kIGFwcGVuZCBhcyBhIG5ldyBjb2x1bW4NCiAgICBkYXRhW1t0cmFuc2Zvcm1lZF92YXJdXSA8LSB0cmFuc2Zvcm1fZm4oZGF0YVtbdmFyXV0pDQogIH0NCiAgcmV0dXJuKGRhdGEpDQp9DQoNCiMgRGVmaW5lIHRyYW5zZm9ybWF0aW9ucyBhcyBhIG5hbWVkIGxpc3QuIFlvdSBjYW4gYWRkIGFwcHJvcHJpYXRlIHRyYW5zZm9ybWF0aW9ucyBoZXJlLCB0aGVuIG9uY2UgeW91IGNvbmZpcm0gdGhlIHRyYW5zZm9ybWF0aW9uIGlzIHN1aXRhYmxlLCBhbWVuZCB0aGUgYW5vdmEgY29kZSB0byBjYWxsIHRoZSBjb3JyZWN0IHZhcmlhYmxlDQoNCiMgVXNlICdpZGVudGl0eScgaWYgbm8gdHJhbnNmb3JtYXRpb24gaXMgbmVlZGVkDQp0cmFuc2Zvcm1hdGlvbnMgPC0gbGlzdCgNCiAgc2FnaXR0YWxfYXJlYSA9IGlkZW50aXR5LCAjIGV4YW1wbGUgY29kZSBmbyBsb2ctdHJhbnNmb3JtYXRpb246IHJlcGxhY2UgJ2lkZW50aXR5LCcgd2l0aCAnZnVuY3Rpb24oeCkgaWZlbHNlKHggPiAwLCBsb2coeCksIE5BKSwnIA0KICBtYXhfcmVzaWR1YWxfZGVwdGggPSBpZGVudGl0eSwgICMgTm8gdHJhbnNmb3JtYXRpb24NCiAgcG9vbF9sZW5ndGggPSBpZGVudGl0eSAjIG5vIHRyYW5zZm9ybWF0aW9uIA0KKQ0KDQojIEFwcGx5IHRyYW5zZm9ybWF0aW9ucyBhbmQgdXBkYXRlIHRoZSBkYXRhZnJhbWUNCnBvb2xfc3VtbWFyeV9maWx0ZXJlZCA8LSBhcHBseV90cmFuc2Zvcm1hdGlvbnMocG9vbF9zdW1tYXJ5X2ZpbHRlcmVkLCB0cmFuc2Zvcm1hdGlvbnMpDQpgYGANCiANCiMjIyBBTk9WQSANCg0KT25jZSB5b3UgaGF2ZSBzYXRpc2ZpZWQgeW91cnNlbGYgdGhhdCB5b3VyIGRhdGEgKG9yIHRyYW5zZm9ybWVkIGRhdGEpIGFyZSBzdWl0YWJsZSwgd2Ugd2lsbCBydW4gdGhlIGluZmVyZW50aWFsIHRlc3RzLiBXZSB1c2UgQU5PVkEgdG8gYXNrIHdoZXRoZXIgdGhlIGZvbGxvd2luZyBtZXRyaWNzIGRpZmZlciBhbW9uZyBzaXRlcywgeWVhcnMsIGFuZCBzaXRlKnllYXIgaW50ZXJhY3Rpb25zOg0KDQotIFNhZ2l0dGFsIGFyZWENCi0gTWF4aW11bSByZXNpZHVhbCBkZXB0aA0KLSBQb29sIGxlbmd0aA0KDQpJZiB5b3UgZGlkIHVzZSB0cmFuc2Zvcm1lZCBkYXRhLCBlbnN1cmUgeW91IHJlZmVyZW5jZSB0aGF0IHZhcmlhYmxlIGluIHRoZSBiZWxvdyBjb2RlIChlLmcuLCBjaGFuZ2UgInNhZ2l0dGFsX2FyZWEiIHRvICJ0cmFuc2Zvcm1lZF9zYWdpdHRhbF9hcmVhIikNCg0KYGBge3IgcG9vbCBBTk9WQXN9DQojIEZ1bmN0aW9uIHRvIHJ1biBBTk9WQSBmb3IgYSBnaXZlbiB2YXJpYWJsZQ0KcnVuX2Fub3ZhIDwtIGZ1bmN0aW9uKGRhdGEsIHZhcmlhYmxlKSB7DQogIGZvcm11bGEgPC0gYXMuZm9ybXVsYShwYXN0ZSh2YXJpYWJsZSwgIn4gU2l0ZSAqIFRpbWVfQ2F0ZWdvcnkiKSkNCiAgYW5vdmFfcmVzdWx0IDwtIGFvdihmb3JtdWxhLCBkYXRhID0gZGF0YSkNCiAgc3VtbWFyeShhbm92YV9yZXN1bHQpDQp9DQoNCiMgRW5zdXJlIHRyYW5zZm9ybWVkIGRhdGEgaXMgdXNlZCBpbiB0aGUgQU5PVkEgaWYgbmVjZXNzYXJ5IChjaGFuZ2UgdGhlIHZhcmlhYmxlIG5hbWUgaW4gcXVvdGF0aW9uIG1hcmtzIGluIHRoZXNlIG5leHQgcm93cykNCmFub3ZhX21heF9yZXNpZHVhbF9kZXB0aCA8LSBydW5fYW5vdmEocG9vbF9zdW1tYXJ5X2ZpbHRlcmVkLCAibWF4X3Jlc2lkdWFsX2RlcHRoIikNCmFub3ZhX3Bvb2xfbGVuZ3RoIDwtIHJ1bl9hbm92YShwb29sX3N1bW1hcnlfZmlsdGVyZWQsICJwb29sX2xlbmd0aCIpDQphbm92YV9zYWdpdHRhbF9hcmVhIDwtIHJ1bl9hbm92YShwb29sX3N1bW1hcnlfZmlsdGVyZWQsICJzYWdpdHRhbF9hcmVhIikNCmBgYA0KDQpgYGB7ciB2aWV3IHBvb2wgQU5PVkFzLCBlY2hvID0gRkFMU0V9DQojIHZpZXcgcmVzdWx0cw0KcHJpbnQoIl9fX19fX19fX19fX19fX0FOT1ZBIGZvciBNYXggUmVzaWR1YWwgRGVwdGhfX19fX19fX19fX19fXyIpDQpwcmludChhbm92YV9tYXhfcmVzaWR1YWxfZGVwdGgpDQpwcmludCgiX19fX19fX19fX19fX19fQU5PVkEgZm9yIFJlc2lkdWFsIFBvb2wgTGVuZ3RoX19fX19fX19fX19fX18iKQ0KcHJpbnQoYW5vdmFfcG9vbF9sZW5ndGgpDQpwcmludCgiX19fX19fX19fX19fX19fQU5PVkEgZm9yIFJlc2lkdWFsIFBvb2wgU2FnaXR0YWwgQXJlYV9fX19fX19fX19fX19fIikNCnByaW50KGFub3ZhX3NhZ2l0dGFsX2FyZWEpDQoNCiMgZXhwb3J0IHRlc3Qgc3VtbWFyaWVzDQptYXhkZWVwX291dHB1dCA8LSBjYXB0dXJlLm91dHB1dChwcmludChhbm92YV9tYXhfcmVzaWR1YWxfZGVwdGgpKSAgIyBDYXB0dXJlIHRoZSBwcmludGVkIG91dHB1dHMNCnBvb2xsb25nX291dHB1dCA8LSBjYXB0dXJlLm91dHB1dChwcmludChhbm92YV9wb29sX2xlbmd0aCkpICAjIA0Kc2FnZ2lfb3V0cHV0IDwtIGNhcHR1cmUub3V0cHV0KHByaW50KGFub3ZhX3NhZ2l0dGFsX2FyZWEpKSAgIyANCnN1bW1hcnlfdGV4dCA8LSBjKCJBTk9WQSBmb3IgTWF4IFJlc2lkdWFsIERlcHRoOiIsIG1heGRlZXBfb3V0cHV0LCAiXG5cblxuIiwgIkFOT1ZBIGZvciBSZXNpZHVhbCBQb29sIExlbmd0aDoiLCBwb29sbG9uZ19vdXRwdXQsIlxuXG5cbiIsICAiQU5PVkEgZm9yIFJlc2lkdWFsIFBvb2wgU2FnaXR0YWwgQXJlYToiLCBzYWdnaV9vdXRwdXQpDQpleHBvcnRfc3VtbWFyeShzdW1tYXJ5X3RleHQsICJSZXNpZHVhbCBQb29sIEFOT1ZBcyIpDQpgYGANCg0KVGFrZSBzb21lIHRpbWUgdG8gZW5zdXJlIHlvdSB1bmRlcnN0YW5kIHdoYXQgdGhlIGFib3ZlIHRlbGxzIHlvdSwgcGFydGljdWxhcmx5IHdpdGggcmVnYXJkcyB0byB5b3VyIGNob3NlbiBtZXRyaWMgb2Ygc3VjY2Vzcy4gSW4gdGhlIGV4YW1wbGUgQU5PVkEgYWJvdmUsIHRoZXJlIHdhcyBvbmUgc2l0ZTp0aW1lIGludGVyYWN0aW9uIHRoYXQgd2FzIHNpZ25pZmljYW50IGF0IHA9MC4wNSAobWF4aW11bSByZXNpZHVhbCBkZXB0aCksIGFuZCB0aGUgdGltZSBjYXRlZ29yeSB3YXMgc2lnbmlmaWNhbnQgZm9yIGFsbCBtZXRyaWNzLiBUaGlzIHN1Z2dlc3RzIHRoYXQgYSBjaGFuZ2UgaW4gbWV0cmljcyBvdmVyIHRpbWUgd2FzIG5vdCBsaWtlbHkgZHVlIHRvIGNoYW5jZSwgYnV0IG9ubHkgZm9yIG1heGltdW0gcmVzaWR1YWwgZGVwdGggZGlkIG91ciByZXN0b3JhdGlvbiBzaXRlIGNoYW5nZSBvdmVyIHRpbWUgZGlmZmVyZW50bHkgdGhhbiB0aGUgY29udHJvbCBzaXRlLiBIb3dldmVyLCB3ZSBjaG9zZSBzYWdpdHRhbCBhcmVhIGFzIG91ciAqYSBwcmlvcmkqIHN1Y2Nlc3MgbWV0cmljLCBzbyB3ZSBjYW5ub3QgaW50ZXJwcmV0IHRoaXMgYXMgYSBzdWNjZXNzZnVsIHJlc3RvcmF0aW9uIGFjdGlvbiBhdCB0aGlzIHBvaW50IGluIHRpbWUuDQoNCkFsdGhvdWdoIHdlIGNvdWxkIG5vdCBkaXNjYXJkIG91ciBhbHRlcm5hdGl2ZSBoeXBvdGhlc2lzICh0aGF0IGNoYW5nZXMgYXQgb3VyIHJlc3RvcmF0aW9uIHNpdGUgd2VyZSBub3QgZHVlIHRvIG91ciBhY3Rpb25zKSwgd2UgbWF5IHN0aWxsIGxlYXJuIGZyb20gdGhlIGFib3ZlIHRvIGluZm9ybSBmdXR1cmUgcGxhbnMuIENvbnNpZGVyIGFsbCB0aGUgaW5mb3JtYXRpb24gd2UgaGF2ZSBnZW5lcmF0ZWQgc28gZmFyIGZvciB5b3UgZGF0YSwgYW5kIHRha2Ugc29tZSB0aW1lIHRvIHRoaW5rIGFib3V0IGl0LiBTdGVwIG91dHNpZGUgdG8gZG8gdGhpcyBpZiB5b3UgYXJlIGFibGUgdG8uIENvbnNpZGVyIHdoYXQgaXQgbWlnaHQgbWVhbiBpZiBwb29scyBhdCBvdXIgcmVzdG9yYXRpb24gc2l0ZSBhcHBlYXIgZGVlcGVyIG9uIGF2ZXJhZ2UsIGJ1dCBzYWdpdHRhbCBhcmVhcyBkaWQgbm90IGNoYW5nZT8gQ29uc2lkZXIgd2hldGhlciB0aGVyZSBhcmUgcG9vbHMgdGhhdCBkaWQgb3IgZGlkIG5vdCBzY3JhcGUgdGhyb3VnaCB0aGUgc3Vic2V0dGluZyBjdXQtb2ZmIChpLmUuLCB2ZXJ5IHNtYWxsIHBvb2xzIG9mIG1hcmdpbmFsIHZhbHVlKSwgaG93IG1pZ2h0IHRoZXkgaW1wYWN0IHlvdXIgbWVhbiB2YWx1ZXM/IFdhcyB0aGVyZSBhIGJpZyBlbm91Z2ggY2hhbmdlIGluIHRoZXNlIG1hcmdpbmFsIGNhc2VzIHRvIGNyZWF0ZSBzdGF0aXN0aWNhbCBzaWduaWZpY2FuY2U/IElzIGFueSBvZiB0aGlzIGJpb2xvZ2ljYWxseSBvciBnZW9tb3JwaGljYWxseSBtZWFuaW5nZnVsIGJhc2VkIG9uIHlvdXIgaHlwb3RoZXNlcz8NCg0KVGhpcyBpcyBhbGwgZW5kbGVzc2x5IGludGVyZXN0aW5nL21hZGRlbmluZyAoZGVwZW5kaW5nIG9uIHlvdXIgcGVyc3BlY3RpdmUpIGFuZCB3ZSBoaWdobHkgcmVjb21tZW5kIGZpbmRpbmcgYW5vdGhlciBwZXJzb24gKG9yIHNldmVyYWwpIHRvIHRhbGsgaXQgdGhyb3VnaCB3aXRoLiBCZWZvcmUgbW92aW5nIG9uIHRvIGZ1cnRoZXIgYW5hbHlzZXMsIGVuc3VyZSB5b3UgaGF2ZSBhIHJlYXNvbmFibGUgdW5kZXJzdGFuZGluZyBvZiB0aGUgaW5mb3JtYXRpb24gc28gZmFyLiBUYWtlIGEgc3RlcCBiYWNrIHRvIHRoaW5rIGFib3V0IHRoZSBiaWcgcGljdHVyZS4NCg0KIyBWb2x1bWUgRXN0aW1hdGlvbg0KDQpJZiB5b3UgaGF2ZSBubyBoeXBvdGhlc2VzIG9yIHByZWRpY3Rpb25zIHNwZWNpZmljYWxseSByZWdhcmRpbmcgcG9vbCAqdm9sdW1lcyosIHlvdSBtYXkgd2lzaCB0byBza2lwIHRoaXMgc2VjdGlvbiBhbmQgbW92ZSBvbnRvICpGaW5lIFNlZGltZW50IGluIFBvb2xzKi4NCg0KSWYgeW91IHRvb2sgd2V0dGVkIHdpZHRoIG1lYXN1cmVtZW50cyBhdCB0cmFuc2VjdHMgYWxvbmcgdGhlIHJlYWNoLCB5b3UgY2FuIHVzZSB0aGUgYXZlcmFnZSB0byBlc3RpbWF0ZSB0aGUgdm9sdW1lIG9mIHJlc2lkdWFsIHBvb2xzLiBUaGlzIGFwcHJvYWNoIGlzIGEgbW9yZSBzaW1wbGlmaWVkIGFwcHJvYWNoIHRoYW4gdGhhdCBvZiBSb2Jpc29uICgxOTk4KSB3aG8gbGlua2VkIHdldHRlZCB3aWR0aCBtZWFzdXJlbWVudHMgdG8gbmVhcmJ5IGxvbmdpdHVkaW5hbCBpbnRlcnZhbHMuIElmIHRoaXMgaXMgcG9zc2libGUgZm9yIHRoZSBkYXRhIHlvdSBjb2xsZWN0ZWQsIHdlIHJlY29tbWVuZCByZXZpZXdpbmcgUm9iaXNvbiAoMTk5OCkgdG8gb2J0YWluIG1vcmUgJ2xvY2FsaXNlZCcgZXN0aW1hdGVzIG9mIHdldHRlZCB3aWR0aC4gSG93ZXZlciwgYmVhciBpbiBtaW5kIHRoYXQgdGhlcmUgbWF5IHJlZ2FyZGxlc3MgYmUgYSBiaWFzIGluIHJlc2lkdWFsIHdldHRlZCB3aWR0aHMgaWYgKGUuZy4pIHBvb2xzIHRlbmQgdG8gYmUgd2lkZXIgdGhhbiByaWZmbGVzLiBGb3Igb3VyIHNpbXBsaWZpZWQgYXBwcm9hY2ggd2UgYXNzdW1lIHRoYXQgdGhlIHdldHRlZCB3aWR0aCBpcyBjb25zdGFudCBmb3IgdGhlIHJlYWNoLCBhbmQgd2UgYWxzbyBhc3N1bWUgdGhhdCB0aGUgc3RyZWFtIGNyb3NzIHNlY3Rpb25zIGFyZSBwZXJmZWN0IHRyaWFuZ2xlcy4gV2UgdGhlbiB1c2UgdGhlIHJhdGlvIG9mIHJlc2lkdWFsIGRlcHRocyB0byBmaWVsZC1yZWNvcmRlZCBkZXB0aHMgdG8gZXN0aW1hdGUgdGhlIHJlc2lkdWFsIHdldHRlZCB3aWR0aHMgb2YgcG9vbHMgd2hlbiBmbG93IGFwcHJvYWNoZXMgemVyby4gDQoNCkNvbnNpZGVyaW5nIGNoYW5nZXMgaW4gKGNvYXJzZWx5LWVzdGltYXRlZCkgcG9vbCB2b2x1bWUgY2FuIGJlIG9mIGludGVyZXN0IGR1ZSB0byB0aGUgcG90ZW50aWFsIGZvciBuYXR1cmFsIHByb2Nlc3NlcyB0byBhbHRlciBib3RoIHRoZSBsb25naXR1ZGluYWwgYW5kIGNyb3NzLXNlY3Rpb25hbCBoZXRlcm9nZW5laXR5IG9mIGEgc3RyZWFtLiBGb3IgZXhhbXBsZSwgcGVyaGFwcyB3ZSBhcmUgYW50aWNpcGF0aW5nIGEgbmFycm93ZXIgd2V0dGVkIGNoYW5uZWwgd2l0aCBkZWVwZXIgcG9vbHMsIGFuZCB3YW50IHRvIGV4cGxvcmUgd2hhdCB0aGlzIG1lYW5zIGZvciBwb29sIHZvbHVtZS4gSG93ZXZlciwgYXMgc3VnZ2VzdGVkIGJ5IHRoZSBjb2Fyc2UgYXNzdW1wdGlvbnMgd2UgbWFkZSBmb3IgdGhpcyBjYWxjdWxhdGlvbiwgaW50ZXJwcmV0IHJlc3VsdHMgd2l0aCBjYXV0aW9uLiANCg0KYGBge3IgcG9vbCB2b2x1bWVzLCBlY2hvID0gRkFMU0V9DQpjYWxjdWxhdGVfcG9vbF92b2x1bWVzX2Zvcl9zaXRlc195ZWFycyA8LSBmdW5jdGlvbihkZiwgcG9vbF9zdW1tYXJ5X2RmKSB7DQogICMgSW5pdGlhbGl6ZSBhIGxpc3QgdG8gc3RvcmUgcmVzdWx0cyBmb3IgZWFjaCBzaXRlLXllYXIgY29tYmluYXRpb24NCiAgcG9vbF92b2x1bWVzX2xpc3QgPC0gbGlzdCgpDQogIA0KICAjIEdyb3VwIHRoZSBkYXRhIGJ5IFNpdGUgYW5kIFllYXINCiAgZ3JvdXBlZF9wb29sX3N1bW1hcnkgPC0gc3BsaXQocG9vbF9zdW1tYXJ5X2RmLCBsaXN0KHBvb2xfc3VtbWFyeV9kZiRTaXRlLCBwb29sX3N1bW1hcnlfZGYkeWVhcikpDQogIA0KICAjIEl0ZXJhdGUgb3ZlciBlYWNoIFNpdGUtWWVhciBncm91cA0KICBmb3IgKGdyb3VwX25hbWUgaW4gbmFtZXMoZ3JvdXBlZF9wb29sX3N1bW1hcnkpKSB7DQogICAgIyBHZXQgdGhlIGN1cnJlbnQgZ3JvdXANCiAgICBncm91cCA8LSBncm91cGVkX3Bvb2xfc3VtbWFyeVtbZ3JvdXBfbmFtZV1dDQogICAgDQogICAgIyBFeHRyYWN0IHRoZSBzaXRlIGFuZCB5ZWFyDQogICAgc2l0ZSA8LSB1bmlxdWUoZ3JvdXAkU2l0ZSkNCiAgICB5ZWFyIDwtIHVuaXF1ZShncm91cCR5ZWFyKQ0KICAgIA0KICAgICMgQ2hlY2sgaWYgc2l0ZSBvciB5ZWFyIGFyZSBpbnZhbGlkDQogICAgaWYgKGxlbmd0aChzaXRlKSAhPSAxIHx8IGxlbmd0aCh5ZWFyKSAhPSAxIHx8IGlzLm5hKHNpdGUpIHx8IGlzLm5hKHllYXIpKSB7DQogICAgICB3YXJuaW5nKHNwcmludGYoIkludmFsaWQgU2l0ZSBvciBZZWFyIGluIGdyb3VwOiAlcy4gU2tpcHBpbmcuLi4iLCBncm91cF9uYW1lKSkNCiAgICAgIG5leHQNCiAgICB9DQogICAgDQogICAgIyBGaWx0ZXIgdGhlIG1haW4gZGF0YWZyYW1lIHRvIG1hdGNoIHRoZSBjdXJyZW50IFNpdGUtWWVhcg0KICAgIHNpdGVfeWVhcl9kYXRhIDwtIGRmW2RmJFNpdGUgPT0gc2l0ZSAmIGRmJHllYXIgPT0geWVhciwgXQ0KICAgIA0KICAgICMgQ2hlY2sgaWYgdGhlIHN1YnNldCBpcyBlbXB0eQ0KICAgIGlmIChucm93KHNpdGVfeWVhcl9kYXRhKSA9PSAwKSB7DQogICAgICB3YXJuaW5nKHNwcmludGYoIk5vIGRhdGEgZm91bmQgZm9yIFNpdGUgJyVzJyBhbmQgWWVhciAnJXMnLiBTa2lwcGluZy4uLiIsIHNpdGUsIHllYXIpKQ0KICAgICAgbmV4dA0KICAgIH0NCiAgICANCiAgICAjIEdldCB0aGUgc3Vic2V0IG9mIHBvb2wgSURzIGZvciB0aGlzIGdyb3VwDQogICAgc3Vic2V0X3Bvb2xfaWRzIDwtIGFzLm51bWVyaWMoZ3JvdXAkcG9vbF9pZCkgICMgQ29udmVydCB0byBudW1lcmljIGlmIG5lY2Vzc2FyeQ0KICAgIA0KICAgICMgRW5zdXJlIHRoZSBkYXRhZnJhbWUgaXMgc29ydGVkIGJ5IGRpc3RhbmNlDQogICAgc2l0ZV95ZWFyX2RhdGEgPC0gc2l0ZV95ZWFyX2RhdGFbb3JkZXIoc2l0ZV95ZWFyX2RhdGEkZGlzdGFuY2UpLCBdDQogICAgDQogICAgIyBGaWx0ZXIgdGhlIGRhdGFmcmFtZSB0byBvbmx5IGluY2x1ZGUgcm93cyBiZWxvbmdpbmcgdG8gdGhlIHN1YnNldCBvZiBwb29sIElEcw0KICAgIHNpdGVfeWVhcl9kYXRhIDwtIHNpdGVfeWVhcl9kYXRhW3NpdGVfeWVhcl9kYXRhJHBvb2xfaWQgJWluJSBzdWJzZXRfcG9vbF9pZHMsIF0NCiAgICANCiAgICAjIEluaXRpYWxpemUgYSBsaXN0IHRvIHN0b3JlIHZvbHVtZXMgZm9yIGVhY2ggcG9vbCBpbiB0aGlzIFNpdGUtWWVhciBncm91cA0KICAgIHBvb2xfdm9sdW1lcyA8LSBsaXN0KCkNCiAgICANCiAgICAjIEl0ZXJhdGUgb3ZlciB1bmlxdWUgcG9vbCBJRHMgaW4gdGhlIHN1YnNldA0KICAgIGZvciAocG9vbF9pZCBpbiBzdWJzZXRfcG9vbF9pZHMpIHsNCiAgICAgICMgU3Vic2V0IHRoZSBkYXRhIGZvciB0aGUgY3VycmVudCBwb29sDQogICAgICBwb29sX2RhdGEgPC0gc2l0ZV95ZWFyX2RhdGFbc2l0ZV95ZWFyX2RhdGEkcG9vbF9pZCA9PSBwb29sX2lkLCBdDQogICAgICANCiAgICAgICMgU2tpcCBpZiB0aGVyZSBhcmUgZmV3ZXIgdGhhbiAyIHBvaW50cyBpbiB0aGUgJ3Bvb2wnIChpbmNsdWRpbmcgb3V0bGV0LCBpLmUuIG5vdCBwb29scykNCiAgICAgIGlmIChucm93KHBvb2xfZGF0YSkgPCAyKSB7DQogICAgICAgIHBvb2xfdm9sdW1lc1tbYXMuY2hhcmFjdGVyKHBvb2xfaWQpXV0gPC0gTkENCiAgICAgICAgbmV4dA0KICAgICAgfQ0KICAgICAgDQogICAgICAjIEluaXRpYWxpemUgdGhlIHBvb2wgdm9sdW1lDQogICAgICBwb29sX3ZvbHVtZSA8LSAwDQogICAgICANCiAgICAgICMgTG9vcCB0aHJvdWdoIGNvbnNlY3V0aXZlIHJvd3MgdG8gY2FsY3VsYXRlIHNlZ21lbnQgdm9sdW1lcw0KICAgICAgZm9yIChpIGluIDE6KG5yb3cocG9vbF9kYXRhKSAtIDEpKSB7DQogICAgICAgICMgUmVzaWR1YWwgd2lkdGggYW5kIGRlcHRoIGZvciBjdXJyZW50IGFuZCBuZXh0IHBvaW50DQogICAgICAgIHdpZHRoX2kgPC0gcG9vbF9kYXRhJHJlc2lkdWFsX3dpZHRoW2ldDQogICAgICAgIGRlcHRoX2kgPC0gcG9vbF9kYXRhJHJlc2lkdWFsX2RlcHRoW2ldDQogICAgICAgIHdpZHRoX25leHQgPC0gcG9vbF9kYXRhJHJlc2lkdWFsX3dpZHRoW2kgKyAxXQ0KICAgICAgICBkZXB0aF9uZXh0IDwtIHBvb2xfZGF0YSRyZXNpZHVhbF9kZXB0aFtpICsgMV0NCiAgICAgICAgDQogICAgICAgICMgQ2hlY2sgZm9yIE5BIHZhbHVlcw0KICAgICAgICBpZiAoaXMubmEod2lkdGhfaSkgfHwgaXMubmEoZGVwdGhfaSkgfHwgaXMubmEod2lkdGhfbmV4dCkgfHwgaXMubmEoZGVwdGhfbmV4dCkpIHsNCiAgICAgICAgICBuZXh0DQogICAgICAgIH0NCiAgICAgICAgDQogICAgICAgICMgQ2FsY3VsYXRlIGNyb3NzLXNlY3Rpb25hbCBhcmVhcw0KICAgICAgICBhcmVhX2kgPC0gMC41ICogd2lkdGhfaSAqIGRlcHRoX2kNCiAgICAgICAgYXJlYV9uZXh0IDwtIDAuNSAqIHdpZHRoX25leHQgKiBkZXB0aF9uZXh0DQogICAgICAgIA0KICAgICAgICAjIENhbGN1bGF0ZSBtZWFuIGNyb3NzLXNlY3Rpb25hbCBhcmVhDQogICAgICAgIG1lYW5fYXJlYSA8LSAoYXJlYV9pICsgYXJlYV9uZXh0KSAvIDINCiAgICAgICAgDQogICAgICAgICMgQ2FsY3VsYXRlIGRpc3RhbmNlIGJldHdlZW4gY3VycmVudCBhbmQgbmV4dCBwb2ludA0KICAgICAgICBzcGFjaW5nIDwtIHBvb2xfZGF0YSRkaXN0YW5jZVtpICsgMV0gLSBwb29sX2RhdGEkZGlzdGFuY2VbaV0NCiAgICAgICAgDQogICAgICAgICMgQWRkIHNlZ21lbnQgdm9sdW1lIHRvIHRvdGFsIHBvb2wgdm9sdW1lDQogICAgICAgIHBvb2xfdm9sdW1lIDwtIHBvb2xfdm9sdW1lICsgbWVhbl9hcmVhICogc3BhY2luZw0KICAgICAgfQ0KICAgICAgDQogICAgICAjIFN0b3JlIHRoZSB2b2x1bWUgZm9yIHRoaXMgcG9vbA0KICAgICAgcG9vbF92b2x1bWVzW1thcy5jaGFyYWN0ZXIocG9vbF9pZCldXSA8LSBwb29sX3ZvbHVtZQ0KICAgIH0NCiAgICANCiAgICAjIENvbnZlcnQgdGhlIHJlc3VsdHMgaW50byBhIGRhdGFmcmFtZSBmb3IgdGhlIGN1cnJlbnQgU2l0ZS1ZZWFyIGdyb3VwDQogICAgcG9vbF92b2x1bWVzX2RmIDwtIGRhdGEuZnJhbWUoDQogICAgICBwb29sX2lkID0gbmFtZXMocG9vbF92b2x1bWVzKSwNCiAgICAgIHBvb2xfdm9sdW1lX20zID0gdW5saXN0KHBvb2xfdm9sdW1lcyksDQogICAgICBTaXRlID0gc2l0ZSwNCiAgICAgIHllYXIgPSB5ZWFyDQogICAgKQ0KICAgIA0KICAgICMgQXBwZW5kIHRoZSByZXN1bHQgZm9yIHRoZSBjdXJyZW50IGdyb3VwIHRvIHRoZSBsaXN0DQogICAgcG9vbF92b2x1bWVzX2xpc3RbW2dyb3VwX25hbWVdXSA8LSBwb29sX3ZvbHVtZXNfZGYNCiAgfQ0KICANCiAgIyBDb21iaW5lIGFsbCBzaXRlLXllYXIgcmVzdWx0cyBpbnRvIGEgc2luZ2xlIGRhdGFmcmFtZQ0KICBmaW5hbF9wb29sX3ZvbHVtZXNfZGYgPC0gZG8uY2FsbChyYmluZCwgcG9vbF92b2x1bWVzX2xpc3QpDQogIA0KICByZXR1cm4oZmluYWxfcG9vbF92b2x1bWVzX2RmKQ0KfQ0KDQojIFVzZSBwb29sX3N1bW1hcnlfcmVzdWx0IGZyb20gdGhlIHByZXZpb3VzIHN0ZXAgdG8gZ2V0IHRoZSBzdWJzZXQgb2YgcG9vbCBJRHMNCnBvb2xfdm9sdW1lc19yZXN1bHQgPC0gY2FsY3VsYXRlX3Bvb2xfdm9sdW1lc19mb3Jfc2l0ZXNfeWVhcnMocmVzaWR1YWxzLmRmLCBwb29sX3N1bW1hcnlfcmVzdWx0KQ0KDQojIERpc3BsYXkgdGhlIHJlc3VsdCBhcyBhIHRhYmxlDQpwb29sX3ZvbHVtZXNfcmVzdWx0IDwtIHBvb2xfdm9sdW1lc19yZXN1bHQgJT4lDQogIHNlbGVjdChTaXRlLCB5ZWFyLCBldmVyeXRoaW5nKCkpICAjIE1vdmUgU2l0ZSBhbmQgWWVhciB0byB0aGUgbGVmdA0KZGF0YXRhYmxlKA0KICBwb29sX3ZvbHVtZXNfcmVzdWx0LA0KICBjYXB0aW9uID0gIlBvb2wgVm9sdW1lcyBieSBTaXRlIGFuZCBZZWFyIiwNCiAgcm93bmFtZXMgPSBGQUxTRSwgICMgSGlkZSByb3cgbnVtYmVycw0KICBvcHRpb25zID0gbGlzdCgNCiAgICBwYWdlTGVuZ3RoID0gMTAsICAjIE51bWJlciBvZiByb3dzIHBlciBwYWdlDQogICAgYXV0b1dpZHRoID0gVFJVRQ0KICApDQopJT4lDQogIGZvcm1hdFJvdW5kKGNvbHVtbnMgPSBuYW1lcyhwb29sX3ZvbHVtZXNfcmVzdWx0KVtzYXBwbHkocG9vbF92b2x1bWVzX3Jlc3VsdCwgaXMubnVtZXJpYyldLCBkaWdpdHMgPSAzKQ0KDQojIEV4cG9ydCB0YWJsZQ0KZXhwb3J0X3RhYmxlKGFzLmRhdGEuZnJhbWUocG9vbF92b2x1bWVzX3Jlc3VsdCksICJSZXNpZHVhbCBQb29sIFZvbHVtZSBFc3RpbWF0ZXMuY3N2IikNCmBgYA0KDQpUaGUgYWJvdmUgdGFibGUgbGlzdHMgdGhlIHZvbHVtZSBlc3RpbWF0ZXMgZm9yIGVhY2ggb2YgdGhlICdtZWFuaW5nZnVsJyBzdWJzZXQgb2YgcmVzaWR1YWwgcG9vbHMsIGFuZCB0aGlzIHRhYmxlIGlzIGFsc28gZXhwb3J0ZWQgdG8geW91ciBvdXRwdXQgZm9sZGVyLiBOZXh0IHdlIHdpbGwgZGlzcGxheSBhbmQgZXhwb3J0IGEgdGFibGUgd2l0aCBzb21lIGtleSBzdW1tYXJ5IHN0YXRpc3RpY3MgZm9yIHRoZSByZWFjaDogVG90YWwgdm9sdW1lIG9mIHJlc2lkdWFsIHBvb2xzLCBhbmQgdGhlIG1lYW4gYW5kIHN0YW5kYXJkIGRldmlhdGlvbiByZXNpZHVhbCB2b2x1bWUgb2YgcG9vbHMuDQoNCmBgYHtyIHBvb2wgdm9sdW1lIHN1bW1hcnkgc3RhdHMsIGVjaG8gPSBGQUxTRX0NCiMgRnVuY3Rpb24gdG8gY2FsY3VsYXRlIHZvbHVtZS1yZWxhdGVkIHN1bW1hcnkgc3RhdGlzdGljcyBmb3IgdGhlIHN1YnNldCBvZiBwb29scw0KY2FsY3VsYXRlX3ZvbHVtZV9zdW1tYXJ5X2Zvcl9zaXRlc195ZWFycyA8LSBmdW5jdGlvbihwb29sX3ZvbHVtZXNfZGYpIHsNCiAgIyBFbnN1cmUgU2l0ZSBhbmQgWWVhciBjb2x1bW5zIGFyZSBwcmVzZW50DQogIGlmICghKCJTaXRlIiAlaW4lIGNvbG5hbWVzKHBvb2xfdm9sdW1lc19kZikpIHx8ICEoInllYXIiICVpbiUgY29sbmFtZXMocG9vbF92b2x1bWVzX2RmKSkpIHsNCiAgICBzdG9wKCJUaGUgZGF0YWZyYW1lIG11c3QgaW5jbHVkZSAnU2l0ZScgYW5kICd5ZWFyJyBjb2x1bW5zLiIpDQogIH0NCiAgDQogICMgU3BsaXQgdGhlIGRhdGEgYnkgU2l0ZSBhbmQgWWVhcg0KICBncm91cGVkX2RhdGEgPC0gc3BsaXQocG9vbF92b2x1bWVzX2RmLCBsaXN0KHBvb2xfdm9sdW1lc19kZiRTaXRlLCBwb29sX3ZvbHVtZXNfZGYkeWVhcikpDQogIA0KICAjIEluaXRpYWxpemUgYSBsaXN0IHRvIHN0b3JlIHN1bW1hcnkgc3RhdGlzdGljcw0KICB2b2x1bWVfc3VtbWFyeV9saXN0IDwtIGxpc3QoKQ0KICANCiAgIyBJdGVyYXRlIG92ZXIgZWFjaCBTaXRlLVllYXIgZ3JvdXANCiAgZm9yIChncm91cF9uYW1lIGluIG5hbWVzKGdyb3VwZWRfZGF0YSkpIHsNCiAgICAjIEdldCB0aGUgY3VycmVudCBncm91cA0KICAgIGdyb3VwIDwtIGdyb3VwZWRfZGF0YVtbZ3JvdXBfbmFtZV1dDQogICAgDQogICAgIyBFeHRyYWN0IFNpdGUgYW5kIFllYXIgKGVuc3VyaW5nIHVuaXF1ZW5lc3MpDQogICAgc2l0ZSA8LSB1bmlxdWUoZ3JvdXAkU2l0ZSkNCiAgICB5ZWFyIDwtIHVuaXF1ZShncm91cCR5ZWFyKQ0KICAgIA0KICAgICMgQ2hlY2sgZm9yIHZhbGlkIFNpdGUgYW5kIFllYXINCiAgICBpZiAobGVuZ3RoKHNpdGUpICE9IDEgfHwgbGVuZ3RoKHllYXIpICE9IDEgfHwgaXMubmEoc2l0ZSkgfHwgaXMubmEoeWVhcikpIHsNCiAgICAgIHdhcm5pbmcoc3ByaW50ZigiSW52YWxpZCBTaXRlIG9yIFllYXIgaW4gZ3JvdXA6ICVzLiBTa2lwcGluZy4uLiIsIGdyb3VwX25hbWUpKQ0KICAgICAgbmV4dA0KICAgIH0NCiAgICANCiAgICAjIENhbGN1bGF0ZSB0b3RhbCByZXNpZHVhbCBwb29sIHZvbHVtZQ0KICAgIHRvdGFsX3Jlc2lkdWFsX3ZvbHVtZSA8LSBzdW0oZ3JvdXAkcG9vbF92b2x1bWVfbTMsIG5hLnJtID0gVFJVRSkNCiAgICANCiAgICAjIENhbGN1bGF0ZSBtZWFuIHJlc2lkdWFsIHBvb2wgdm9sdW1lDQogICAgbWVhbl9yZXNpZHVhbF92b2x1bWUgPC0gbWVhbihncm91cCRwb29sX3ZvbHVtZV9tMywgbmEucm0gPSBUUlVFKQ0KICAgIA0KICAgICMgQ2FsY3VsYXRlIHN0YW5kYXJkIGRldmlhdGlvbiBvZiByZXNpZHVhbCBwb29sIHZvbHVtZQ0KICAgIHNkX3Jlc2lkdWFsX3ZvbHVtZSA8LSBzZChncm91cCRwb29sX3ZvbHVtZV9tMywgbmEucm0gPSBUUlVFKQ0KICAgIA0KICAgICMgQ3JlYXRlIGEgc3VtbWFyeSB0YWJsZSBmb3IgdGhlIGN1cnJlbnQgU2l0ZS1ZZWFyDQogICAgdm9sdW1lX3N1bW1hcnkgPC0gZGF0YS5mcmFtZSgNCiAgICAgIFNpdGUgPSBzaXRlLA0KICAgICAgeWVhciA9IHllYXIsDQogICAgICB0b3RhbF9yZXNpZHVhbF92b2x1bWUgPSB0b3RhbF9yZXNpZHVhbF92b2x1bWUsDQogICAgICBtZWFuX3Jlc2lkdWFsX3ZvbHVtZSA9IG1lYW5fcmVzaWR1YWxfdm9sdW1lLA0KICAgICAgc2RfcmVzaWR1YWxfdm9sdW1lID0gc2RfcmVzaWR1YWxfdm9sdW1lDQogICAgKQ0KICAgIA0KICAgICMgQXBwZW5kIHRoZSBzdW1tYXJ5IHRvIHRoZSBsaXN0DQogICAgdm9sdW1lX3N1bW1hcnlfbGlzdFtbZ3JvdXBfbmFtZV1dIDwtIHZvbHVtZV9zdW1tYXJ5DQogIH0NCiAgDQogICMgQ29tYmluZSBhbGwgU2l0ZS1ZZWFyIHN1bW1hcmllcyBpbnRvIGEgc2luZ2xlIGRhdGFmcmFtZQ0KICBmaW5hbF92b2x1bWVfc3VtbWFyeV9kZiA8LSBkby5jYWxsKHJiaW5kLCB2b2x1bWVfc3VtbWFyeV9saXN0KQ0KICANCiAgcmV0dXJuKGZpbmFsX3ZvbHVtZV9zdW1tYXJ5X2RmKQ0KfQ0KDQojIENhbGN1bGF0ZSB0aGUgc3VtbWFyeSBzdGF0aXN0aWNzIGZvciB0aGUgc3Vic2V0IG9mIHBvb2xzIGJhc2VkIG9uIHRoZWlyIHZvbHVtZXMNCnZvbHVtZV9zdW1tYXJ5X3Jlc3VsdCA8LSBjYWxjdWxhdGVfdm9sdW1lX3N1bW1hcnlfZm9yX3NpdGVzX3llYXJzKHBvb2xfdm9sdW1lc19yZXN1bHQpDQoNCiMgRGlzcGxheSB0aGUgcmVzdWx0IGFzIGEgdGFibGUNCnZvbHVtZV9zdW1tYXJ5X3Jlc3VsdCA8LSB2b2x1bWVfc3VtbWFyeV9yZXN1bHQgJT4lDQogIHNlbGVjdChTaXRlLCB5ZWFyLCBldmVyeXRoaW5nKCkpICAjIE1vdmUgU2l0ZSBhbmQgWWVhciB0byB0aGUgbGVmdA0KZGF0YXRhYmxlKA0KICB2b2x1bWVfc3VtbWFyeV9yZXN1bHQsDQogIGNhcHRpb24gPSAiVm9sdW1lIFN1bW1hcnkgU3RhdGlzdGljcyBmb3IgU3Vic2V0IG9mIFBvb2xzIGJ5IFNpdGUgYW5kIFllYXIiLA0KICByb3duYW1lcyA9IEZBTFNFLCAgIyBIaWRlIHJvdyBudW1iZXJzDQogIG9wdGlvbnMgPSBsaXN0KA0KICAgIHBhZ2VMZW5ndGggPSAxMCwgICMgTnVtYmVyIG9mIHJvd3MgcGVyIHBhZ2UNCiAgICBhdXRvV2lkdGggPSBUUlVFDQogICkNCiklPiUNCiAgZm9ybWF0Um91bmQoY29sdW1ucyA9IG5hbWVzKHZvbHVtZV9zdW1tYXJ5X3Jlc3VsdClbc2FwcGx5KHZvbHVtZV9zdW1tYXJ5X3Jlc3VsdCwgaXMubnVtZXJpYyldLCBkaWdpdHMgPSAzKQ0KDQojIEV4cG9ydCB0YWJsZQ0KZXhwb3J0X3RhYmxlKGFzLmRhdGEuZnJhbWUodm9sdW1lX3N1bW1hcnlfcmVzdWx0KSwgIlJlYWNoIFJlc2lkdWFsIFBvb2wgVm9sdW1lIE1ldHJpY3MgYnkgU2l0ZSBhbmQgWWVhci5jc3YiKQ0KYGBgDQoNCiMjIEluZmVyZW50aWFsIFRlc3RzIC0gVm9sdW1lDQoNCkZvbGxvd2luZyB0aGUgc2FtZSBhcHByb2FjaCBhcyBmb3IgdGhlIG9uZS0gYW5kIHR3by1kaW1lbnNpb25hbCBwb29sIG1ldHJpY3MsIHdlIHdpbGwgdXNlIEFOT1ZBcyB0byB0ZXN0IHRoZSBwb29sIHZvbHVtZSBkaWZmZXJlbmNlcyBiZXR3ZWVuIHNpdGVzIGFuZCB5ZWFycy4NCg0KIyMgQXNzdW1wdGlvbiBSb2J1c3RuZXNzDQoNCkFzIGJlZm9yZSwgdGhlIGZpcnN0IHN0ZXAgaXMgdG8gY2hlY2sgd2hldGhlciBhbiBBTk9WQSBpcyBzdWl0YWJsZSBmb3IgdGhlIHZhcmlhYmxlcy4NCg0KYGBge3Igdm9sdW1lIGRhdGEgZXZhbHVhdGluZywgZWNobz1GQUxTRX0NCiMjIyMgYWRkIHRoZSBiZWZvcmUvYWZ0ZXIgY2F0ZWdvcmllcyBmcm9tIHByZXZpb3VzIGlucHV0DQpwb29sX3ZvbHVtZXNfcmVzdWx0IDwtIHBvb2xfdm9sdW1lc19yZXN1bHQgJT4lDQogIG11dGF0ZShUaW1lX0NhdGVnb3J5ID0gY2FzZV93aGVuKA0KICAgIHllYXIgJWluJSBiZWZvcmVfeWVhcnMgfiAiQmVmb3JlIiwNCiAgICB5ZWFyICVpbiUgYWZ0ZXJfeWVhcnMgfiAiQWZ0ZXIiLA0KICAgIFRSVUUgfiBOQV9jaGFyYWN0ZXJfDQogICkpDQoNCiMgRmlsdGVyIG91dCBzaXRlcyB3aXRob3V0IGJvdGggdGltZSBjYXRlZ29yaWVzLiBSZW1vdmUgcm93cyB3aXRoIHBvb2xfaWQgPSAiVG90YWwiDQpwb29sX3ZvbHVtZXNfZmlsdGVyZWQgPC0gcG9vbF92b2x1bWVzX3Jlc3VsdCAlPiUNCiAgZmlsdGVyKHBvb2xfaWQgIT0gIlRvdGFsIikgJT4lDQogIGdyb3VwX2J5KFNpdGUpICU+JQ0KICBmaWx0ZXIoYWxsKGMoIkJlZm9yZSIsICJBZnRlciIpICVpbiUgVGltZV9DYXRlZ29yeSkpICU+JQ0KICB1bmdyb3VwKCkNCg0KIyMjIyMjIyMjIyMjIyMgU2hhcGlybyBXaWxrIE5vcm1hbGl0eSBUZXN0DQp0ZXN0X25vcm1hbGl0eV92b2x1bWVzIDwtIGZ1bmN0aW9uKHBvb2xfdm9sdW1lc19kZikgew0KICBwb29sX3ZvbHVtZXNfZ3JvdXBlZCA8LSBzcGxpdChwb29sX3ZvbHVtZXNfZGYsIGxpc3QocG9vbF92b2x1bWVzX2RmJFNpdGUsIHBvb2xfdm9sdW1lc19kZiRUaW1lX0NhdGVnb3J5KSkNCiAgbm9ybWFsaXR5X3Jlc3VsdHNfbGlzdCA8LSBsaXN0KCkNCiAgDQogIGZvciAoZ3JvdXBfbmFtZSBpbiBuYW1lcyhwb29sX3ZvbHVtZXNfZ3JvdXBlZCkpIHsNCiAgICBncm91cCA8LSBwb29sX3ZvbHVtZXNfZ3JvdXBlZFtbZ3JvdXBfbmFtZV1dDQogICAgaWYgKG5yb3coZ3JvdXApIDwgMykgew0KICAgICAgbm9ybWFsaXR5X3Jlc3VsdHNfbGlzdFtbZ3JvdXBfbmFtZV1dIDwtIGRhdGEuZnJhbWUoDQogICAgICAgIFNpdGUgPSBOQSwgVGltZV9DYXRlZ29yeSA9IE5BLA0KICAgICAgICBwb29sX3ZvbHVtZV9tM19wX3ZhbHVlID0gTkEsDQogICAgICAgIG1lc3NhZ2UgPSAiTm90IGVub3VnaCBkYXRhIGZvciBub3JtYWxpdHkgdGVzdCINCiAgICAgICkNCiAgICAgIG5leHQNCiAgICB9DQogICAgcG9vbF92b2x1bWVfdGVzdCA8LSBzaGFwaXJvLnRlc3QoZ3JvdXAkcG9vbF92b2x1bWVfbTMpDQogICAgDQogICAgbm9ybWFsaXR5X3Jlc3VsdHNfbGlzdFtbZ3JvdXBfbmFtZV1dIDwtIGRhdGEuZnJhbWUoDQogICAgICBTaXRlID0gdW5pcXVlKGdyb3VwJFNpdGUpLA0KICAgICAgVGltZV9DYXRlZ29yeSA9IHVuaXF1ZShncm91cCRUaW1lX0NhdGVnb3J5KSwNCiAgICAgIHBvb2xfdm9sdW1lX20zX3BfdmFsdWUgPSBwb29sX3ZvbHVtZV90ZXN0JHAudmFsdWUsDQogICAgICBtZXNzYWdlID0gIk5vcm1hbGl0eSB0ZXN0IGNvbXBsZXRlZCINCiAgICApDQogIH0NCiAgbm9ybWFsaXR5X3Jlc3VsdHNfZGYgPC0gZG8uY2FsbChyYmluZCwgbm9ybWFsaXR5X3Jlc3VsdHNfbGlzdCkNCiAgcmV0dXJuKG5vcm1hbGl0eV9yZXN1bHRzX2RmKQ0KfQ0KDQojIFRlc3Qgbm9ybWFsaXR5IGZvciBwb29sIHZvbHVtZXMNCm5vcm1hbGl0eV9yZXN1bHRzX3ZvbHVtZXMgPC0gdGVzdF9ub3JtYWxpdHlfdm9sdW1lcyhwb29sX3ZvbHVtZXNfZmlsdGVyZWQpDQojIGRpc3BsYXkgaW4gdGFibGUNCm5vcm1hbGl0eV9yZXN1bHRzX3ZvbHVtZXMgJT4lDQogIG11dGF0ZSgNCiAgICBwb29sX3ZvbHVtZV9tM19wX3ZhbHVlID0gcm91bmQocG9vbF92b2x1bWVfbTNfcF92YWx1ZSwgMykNCiAgKSAlPiUNCiAga2FibGUoDQogICAgY2FwdGlvbiA9ICJOb3JtYWxpdHkgVGVzdCBSZXN1bHRzIGZvciBQb29sIFZvbHVtZSBEYXRhIiwNCiAgICBjb2wubmFtZXMgPSBjKCJTaXRlIiwgIlRpbWUgQ2F0ZWdvcnkiLCANCiAgICAgICAgICAgICAgICAgICJQb29sIFZvbHVtZSBQLVZhbHVlIiwgDQogICAgICAgICAgICAgICAgICAiTWVzc2FnZSIpLA0KICAgIGFsaWduID0gImMiLCAgIyBDZW50ZXItYWxpZ24gdGhlIGNvbHVtbnMNCiAgICByb3cubmFtZXMgPSBGQUxTRQ0KICApICMgbG9vayBvdXQgZm9yIHAgdmFsdWVzIDwwLjA1IHdoaWNoIGluZGljYXRlIG5vbi1ub3JtYWxpdHkNCg0KIyMjIyMjIyMjIyMjIyMjIExldmVuZXMgdGVzdCBmb3IgZXF1YWxpdHkgb2YgdmFyaWFuY2UNCnJ1bl9sZXZlbmVzX3Rlc3Rfdm9sdW1lcyA8LSBmdW5jdGlvbihwb29sX3ZvbHVtZXNfZGYpIHsNCiAgIyBMZXZlbmUncyB0ZXN0IGZvciBwb29sIHZvbHVtZXMNCiAgbGV2ZW5lX3Rlc3QgPC0gbGV2ZW5lVGVzdChwb29sX3ZvbHVtZV9tMyB+IGludGVyYWN0aW9uKFNpdGUsIHllYXIpLCBkYXRhID0gcG9vbF92b2x1bWVzX2RmKQ0KICByZXR1cm4obGV2ZW5lX3Rlc3QpDQp9DQoNCiMgUnVuIExldmVuZSdzIHRlc3QgZm9yIHBvb2wgdm9sdW1lcw0KbGV2ZW5lX3Jlc3VsdHNfdm9sdW1lcyA8LSBydW5fbGV2ZW5lc190ZXN0X3ZvbHVtZXMocG9vbF92b2x1bWVzX2ZpbHRlcmVkKQ0KcHJpbnQobGV2ZW5lX3Jlc3VsdHNfdm9sdW1lcykNCg0KIyMjIyMjIyMjIyMjIyMjIyMgRnVuY3Rpb24gdG8gZ2VuZXJhdGUgYWRkaXRpb25hbCBkaWFnbm9zdGljcyBmb3IgcG9vbCB2b2x1bWVzDQpnZW5lcmF0ZV9hc3N1bXB0aW9uX2RpYWdub3N0aWNzIDwtIGZ1bmN0aW9uKHBvb2xfdm9sdW1lc19kZikgew0KICAjIFEtUSBwbG90DQogIHFxX3Bsb3QgPC0gZ2dwbG90KHBvb2xfdm9sdW1lc19kZiwgYWVzKHNhbXBsZSA9IHBvb2xfdm9sdW1lX20zKSkgKw0KICAgIGdlb21fcXEoKSArDQogICAgZ2VvbV9xcV9saW5lKCkgKw0KICAgIGdndGl0bGUoIlEtUSBQbG90IGZvciBQb29sIFZvbHVtZSAobTMpIikNCiAgDQogICMgU2tld25lc3MgYW5kIEt1cnRvc2lzDQogIHNrZXdfdmFsdWUgPC0gc2tld25lc3MocG9vbF92b2x1bWVzX2RmJHBvb2xfdm9sdW1lX20zLCBuYS5ybSA9IFRSVUUpDQogIGt1cnRfdmFsdWUgPC0ga3VydG9zaXMocG9vbF92b2x1bWVzX2RmJHBvb2xfdm9sdW1lX20zLCBuYS5ybSA9IFRSVUUpDQogIA0KICAjIEJveHBsb3QNCiAgYm94cGxvdCA8LSBnZ3Bsb3QocG9vbF92b2x1bWVzX2RmLCBhZXMoeCA9IFNpdGUsIHkgPSBwb29sX3ZvbHVtZV9tMywgZmlsbCA9IFRpbWVfQ2F0ZWdvcnkpKSArDQogICAgZ2VvbV9ib3hwbG90KCkgKw0KICAgIGxhYnModGl0bGUgPSAiQm94cGxvdCBvZiBQb29sIFZvbHVtZSBieSBTaXRlIGFuZCBUaW1lIENhdGVnb3J5IikgKw0KICAgIHRoZW1lKGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGFuZ2xlID0gNDUsIGhqdXN0ID0gMSkpDQogIA0KICAjIFJldHVybiBhbGwgZGlhZ25vc3RpY3MNCiAgcmV0dXJuKGxpc3QoDQogICAgYm94cGxvdCA9IGJveHBsb3QsDQogICAgcXFfcGxvdCA9IHFxX3Bsb3QsDQogICAgc2tld25lc3MgPSBza2V3X3ZhbHVlLA0KICAgIGt1cnRvc2lzID0ga3VydF92YWx1ZQ0KICApKQ0KfQ0KDQojIyMjIEFwcGx5IHRvIHBvb2xfdm9sdW1lc19maWx0ZXJlZA0KZGlhZ25vc3RpY3MgPC0gZ2VuZXJhdGVfYXNzdW1wdGlvbl9kaWFnbm9zdGljcyhwb29sX3ZvbHVtZXNfZmlsdGVyZWQpDQoNCiMjIyMgUHJpbnQgcmVzdWx0cw0KcHJpbnQoZGlhZ25vc3RpY3MkYm94cGxvdCkNCnByaW50KGRpYWdub3N0aWNzJHFxX3Bsb3QpDQpjYXQoIlNrZXduZXNzOiIsIGRpYWdub3N0aWNzJHNrZXduZXNzLCAiXG4iKQ0KY2F0KCJLdXJ0b3NpczoiLCBkaWFnbm9zdGljcyRrdXJ0b3NpcywgIlxuIikNCmBgYA0KV2UgbmVlZGVkIHRvIHRyYW5zZm9ybSBvdXIgdm9sdW1lIGRhdGEsIHdoaWNoIHdhcyBub3Qgbm9ybWFsbHkgZGlzdHJpYnV0ZWQuIEZvbGxvd2luZyB0aGUgc2FtZSB0cmFuc2Zvcm1hdGlvbiBzdGVwcyBhcyBiZWZvcmUsIFdlIHJlcGxhY2VkICdwb29sX3ZvbHVtZV9tMycgd2l0aCB0aGUgbG9nLXRyYW5zZm9ybWVkICd0cmFuc2Zvcm1lZF9wb29sX3ZvbHVtZV9tMycgKHVzaW5nIHRoZSBiZWxvdyBjb2RlKSBhbmQgcmUtcmFuIHRoZSBkaWFnbm9zdGljcy4gT3VyIFEtUSBwbG90IGFuZCB0ZXN0cyBsb29rZWQgbXVjaCBiZXR0ZXIsIHNvIHdlIHVzZWQgdGhlIHRyYW5zZm9ybWVkIHZhcmlhYmxlIGluIHRoZSBBTk9WQS4NCg0KYGBge3Igdm9sdW1lIHRyYW5zZm9ybWF0aW9ufQ0KIyBEZWZpbmUgdHJhbnNmb3JtYXRpb25zIGFzIGEgbmFtZWQgbGlzdCBmb3IgcG9vbCB2b2x1bWUNCnRyYW5zZm9ybWF0aW9ucyA8LSBsaXN0KA0KICBwb29sX3ZvbHVtZV9tMyA9IGZ1bmN0aW9uKHgpIGlmZWxzZSh4ID4gMCwgbG9nKHgpLCBOQSkgICMgTG9nIHRyYW5zZm9ybWF0aW9uIHdpdGggaGFuZGxpbmcgZm9yIG5vbi1wb3NpdGl2ZSB2YWx1ZXMgKHZvbHVtZXMgc2hvdWxkIGFsbCBiZSBwb3NpdGl2ZSEpDQopDQoNCiMgQXBwbHkgdHJhbnNmb3JtYXRpb25zIGFuZCB1cGRhdGUgdGhlIGRhdGFmcmFtZQ0KcG9vbF92b2x1bWVzX2ZpbHRlcmVkIDwtIGFwcGx5X3RyYW5zZm9ybWF0aW9ucyhwb29sX3ZvbHVtZXNfZmlsdGVyZWQsIHRyYW5zZm9ybWF0aW9ucykNCmBgYA0KIyMgQU5PVkEgLSB2b2x1bWUgDQoNCmBgYHtyIGluZmVyZW50aWFsIHRlc3RzIHZvbH0NCiMgRW5zdXJlIHRyYW5zZm9ybWVkIGRhdGEgaXMgdXNlZCBpbiB0aGUgQU5PVkEgZnVuY3Rpb24gaWYgbmVjZXNzYXJ5IChjaGFuZ2UgdGhlIHZhcmlhYmxlIG5hbWUgaW4gcXVvdGF0aW9uIG1hcmtzKQ0KYW5vdmFfcG9vbF92b2x1bWVzIDwtIHJ1bl9hbm92YShwb29sX3ZvbHVtZXNfZmlsdGVyZWQsICJwb29sX3ZvbHVtZV9tMyIpICMgYWRqdXN0IHRvICJ0cmFuc2Zvcm1lZF9wb29sX3ZvbHVtZXNfbTMiIGFzIG5lZWRlZA0KYGBgDQpgYGB7ciBwcmludCB2b2wgQU5PVkFzLCBlY2hvID0gRkFMU0V9DQojcHJpbnQgcmVzdWx0cw0KcHJpbnQoYW5vdmFfcG9vbF92b2x1bWVzKQ0KDQojIGV4cG9ydCB0ZXN0IHN1bW1hcnkNCnZvbF9vdXRwdXQgPC0gY2FwdHVyZS5vdXRwdXQocHJpbnQoYW5vdmFfcG9vbF92b2x1bWVzKSkgICMgQ2FwdHVyZSB0aGUgcHJpbnRlZCBvdXRwdXQNCnN1bW1hcnlfdGV4dCA8LSBjKCJBTk9WQSBmb3IgUmVzaWR1YWwgUG9vbCBWb2x1bWUiLCB2b2xfb3V0cHV0KQ0KZXhwb3J0X3N1bW1hcnkoc3VtbWFyeV90ZXh0LCAiUmVzaWR1YWwgUG9vbCBWb2x1bWUgQU5PVkEiKQ0KYGBgDQpXaGVuIGludGVycHJldGluZyBwb3RlbnRpYWwgY2hhbmdlcyBpbiBwb29sIHZvbHVtZSBtZXRyaWNzLCByZW1lbWJlciB0aGF0IHdlIG5lZWRlZCB0byBtYWtlIGFzc3VtcHRpb25zIHJlZ2FyZGluZyB0aGUgd2lkdGhzIG9mIHJlc2lkdWFsIHBvb2xzLCBtYWtpbmcgdGhlc2Ugdm9sdW1lIG1ldHJpY3MgbW9yZSBzcGVjdWxhdGl2ZSB0aGFuIHNhZ2l0dGFsIGFyZWEgbWV0cmljcy4gV2hpbGUgdm9sdW1lcyBjYW4gYmUgdXNlZnVsIGZvciBpbnRlcnByZXRhdGlvbiwgaWYgdGhlcmUgYXJlIGRpc2FncmVlbWVudHMgYmV0d2VlbiB0aGUgaW5mZXJlbnRpYWwgdGVzdCByZXN1bHRzIGFtb25nIHZvbHVtZS0gYW5kIGFyZWEvbGVuZ3RoLWJhc2VkIG1ldHJpY3MsIHdlIHJlY29tbWVuZCBkZWZhdWx0aW5nIHRvIHRoZSBsYXR0ZXIgKHVubGVzcywgb2YgY291cnNlLCB5b3UgaGF2ZSBhIHNvbGlkIF9hIHByaW9yaV8gaHlwb3RoZXNpcyBhbmQgcHJlZGljdGlvbiB0aGF0IHN1Z2dlc3RzIHZvbHVtZSBzaG91bGQgZGlmZmVyIGluIHRoZSB3YXkgeW91IG9ic2VydmVkKS4NCg0KIyBGaW5lIFNlZGltZW50IGluIFBvb2xzDQoNClRoZSBsb25naXR1ZGluYWwgc3VydmV5IGluY2x1ZGVkIHByZXNlbmNlL2Fic2VuY2Ugb2JzZXJ2YXRpb25zIG9mIGZpbmUgc2VkaW1lbnQgYWxvbmcgdGhlIHRoYWx3ZWcuIEhlcmUgd2Ugd2lsbCBnZW5lcmF0ZSBhIG1ldHJpYyBvZiB0aGUgcHJvcG9ydGlvbiBvZiByZXNpZHVhbCBwb29sIHRoYWx3ZWcgdGhhdCBmZWF0dXJlcyBmaW5lIHNlZGltZW50cy4gDQoNCk5vdGUgdGhhdCwgd2hpbGUgdGhlIHByZXZpb3VzIG1ldHJpY3MgaW4gdGhpcyBzY3JpcHQgdXNlIHRoZSAnY3VzdG9tIGRlcHRoJyB0aHJlc2hvbGQgdG8gc3Vic2V0IHdoYXQgYXJlIGNvbnNpZGVyZWQgJ21lYW5pbmdmdWwnIHBvb2xzLCB3ZSByZWNvbW1lbmQgY29uc2lkZXJpbmcgZmluZSBzZWRpbWVudCByZWxhdGl2ZSB0byB0aGUgZnVsbCBjb250aW5nZW50IG9mIHJlc2lkdWFsIHBvb2xzIHRoYXQgdGhlIGNvZGUgaGFzIGlkZW50aWZpZWQuIE91ciByYXRpb25hbGUgaXMgdGhhdCB0aGUgZmluZXMgbWV0cmljcyByZWxhdGUgbW9yZSBjbG9zZWx5IHRvIHRoZSBtZWNoYW5pc21zIHRoYXQgY2FuIGJlIHJlc3BvbnNpYmxlIGZvciBtYWtpbmcgcG9vbHMgJ21lYW5pbmdmdWwnIChvciBub3QpIGluIHRlcm1zIG9mIGZpc2ggaGFiaXRhdCBhdmFpbGFiaWxpdHkuIElmIHdlIHdlcmUgdG8gbG9vayBhdCB0aGUgcHJvcG9ydGlvbiBvZiBmaW5lcyBvbmx5IGluICdtZWFuaW5nZnVsJyAoZGVlcCBlbm91Z2gpIHBvb2xzLCB3ZSBtaWdodCBtaXNzIHBvb2xzIHRoYXQgYXJlIGNsb3NlciB0byBiZWluZyAnbm90IHBvb2xzJyAoaS5lLiwgcmVjZW50bHkgZmlsbGluZy1pbiBvciBzY291cmluZyBvZiBzZWRpbWVudCkuIE9mIGNvdXJzZSwgd2hlbiBwb29scyBhcmUgZnVsbHkgaW5maWxsZWQgd2l0aCBzZWRpbWVudCB0aGV5IHdpbGwgbm90IGJlIGRldGVjdGVkIGFzIHBvb2xzIGF0IGFsbCwgYnV0IHRoZSBhYmlsaXR5IHRvIHJlY29nbmlzZSB3aGVuIGEgcG9vbCBpcyBmaWxsaW5nIGluIChvciBzY291cmluZyBvdXQpIG1heSBiZSBhbiBpbXBvcnRhbnQgaW5kaWNhdG9yIG9mIHJlc3RvcmF0aW9uIHN1Y2Nlc3MsIG9yIGEgdHJpZ2dlciBmb3IgYWRhcHRpdmUgbWFuYWdlbWVudCBhY3Rpb25zLg0KDQpgYGB7ciBmaW5lcywgZWNobyA9IEZBTFNFfQ0KY2FsY3VsYXRlX2ZpbmVzX3Byb3BvcnRpb24gPC0gZnVuY3Rpb24ocG9vbF9kYXRhLCByZXNpZHVhbHMuZGYsIGN1c3RvbV9kZXB0aF90aHJlc2hvbGQgPSBOVUxMLCB1c2Vfc2RfdGhyZXNob2xkID0gRkFMU0UpIHsNCiAgIyBFbnN1cmUgdGhlIHJlc2lkdWFscyBkYXRhZnJhbWUgaGFzICdTaXRlJyBhbmQgJ3llYXInIGNvbHVtbnMgZm9yIGdyb3VwaW5nDQogIGlmICghYWxsKGMoIlNpdGUiLCAieWVhciIpICVpbiUgY29sbmFtZXMocmVzaWR1YWxzLmRmKSkpIHsNCiAgICBzdG9wKCJyZXNpZHVhbHMuZGYgbXVzdCBjb250YWluICdTaXRlJyBhbmQgJ3llYXInIGNvbHVtbnMuIikNCiAgfQ0KICANCiAgIyBJbml0aWFsaXplIGEgbGlzdCB0byBzdG9yZSByZXN1bHRzDQogIGZpbmVzX3Byb3BvcnRpb25fbGlzdCA8LSBsaXN0KCkNCiAgDQogICMgR3JvdXAgcmVzaWR1YWxzIGJ5IFNpdGUgYW5kIHllYXINCiAgdW5pcXVlX3NpdGVzX3llYXJzIDwtIHVuaXF1ZShyZXNpZHVhbHMuZGZbYygiU2l0ZSIsICJ5ZWFyIildKQ0KICANCiAgZm9yIChpIGluIDE6bnJvdyh1bmlxdWVfc2l0ZXNfeWVhcnMpKSB7DQogICAgc2l0ZSA8LSB1bmlxdWVfc2l0ZXNfeWVhcnMkU2l0ZVtpXQ0KICAgIHllYXIgPC0gdW5pcXVlX3NpdGVzX3llYXJzJHllYXJbaV0NCiAgICANCiAgICAjIFN1YnNldCB0aGUgcmVzaWR1YWxzIGRhdGFmcmFtZSBmb3IgdGhlIGN1cnJlbnQgU2l0ZSBhbmQgeWVhcg0KICAgIHN1YnNldF9yZXNpZHVhbHMgPC0gcmVzaWR1YWxzLmRmW3Jlc2lkdWFscy5kZiRTaXRlID09IHNpdGUgJiByZXNpZHVhbHMuZGYkeWVhciA9PSB5ZWFyLCBdDQogICAgDQogICAgICAgIGlmIChucm93KHN1YnNldF9yZXNpZHVhbHMpID09IDAgfHwgYWxsKGlzLm5hKHN1YnNldF9yZXNpZHVhbHMkcmVzaWR1YWxfZGVwdGgpKSkgew0KICAgIG1lc3NhZ2UocGFzdGUoIlNraXBwaW5nIFNpdGU6Iiwgc2l0ZSwgIlllYXI6IiwgeWVhciwgDQogICAgICAgICAgICAgICAgICAiLSBubyB2YWxpZCByZXNpZHVhbCBkZXB0aCBkYXRhIGF2YWlsYWJsZS4iKSkNCiAgICBuZXh0DQp9DQogICAgIyBFbnN1cmUgdGhlIGRhdGFmcmFtZSBpcyBzb3J0ZWQgYnkgZGlzdGFuY2Ugd2l0aGluIGVhY2ggcG9vbA0KICAgIHN1YnNldF9yZXNpZHVhbHMgPC0gc3Vic2V0X3Jlc2lkdWFsc1tvcmRlcihzdWJzZXRfcmVzaWR1YWxzJHBvb2xfaWQsIHN1YnNldF9yZXNpZHVhbHMkZGlzdGFuY2UpLCBdDQogICAgDQogICAgIyBUcmltIHdoaXRlc3BhY2UgZnJvbSB0aGUgRmluZXMgY29sdW1uDQogICAgc3Vic2V0X3Jlc2lkdWFscyRGaW5lcyA8LSB0cmltd3Moc3Vic2V0X3Jlc2lkdWFscyRGaW5lcykNCiAgICANCiAgICAjIEluaXRpYWxpemUgYSBsaXN0IHRvIHN0b3JlIHJlc3VsdHMgZm9yIHRoZSBjdXJyZW50IFNpdGUveWVhcg0KICAgIGZpbmVzX3Byb3BvcnRpb25fc2l0ZV95ZWFyIDwtIGxpc3QoKQ0KICAgIA0KICAgICMgQ2FsY3VsYXRlIHRoZSBzdGFuZGFyZCBkZXZpYXRpb24gb2YgcmVzaWR1YWwgZGVwdGggaWYgbmVlZGVkDQogICAgaWYgKHVzZV9zZF90aHJlc2hvbGQpIHsNCiAgICAgIHNkX3Jlc2lkdWFsX2RlcHRoIDwtIHNkKHN1YnNldF9yZXNpZHVhbHMkcmVzaWR1YWxfZGVwdGgsIG5hLnJtID0gVFJVRSkNCiAgICB9DQogICAgDQogICAgIyBJdGVyYXRlIG92ZXIgZWFjaCB1bmlxdWUgcG9vbF9pZA0KICAgIHVuaXF1ZV9wb29sX2lkcyA8LSB1bmlxdWUoc3Vic2V0X3Jlc2lkdWFscyRwb29sX2lkKQ0KICAgIGZvciAocG9vbF9pZCBpbiB1bmlxdWVfcG9vbF9pZHMpIHsNCiAgICAgICMgU2tpcCBpZiBwb29sX2lkIGlzIE5BDQogIGlmIChpcy5uYShwb29sX2lkKSkgew0KICAgIG5leHQNCiAgfQ0KICAgICAgIyBTdWJzZXQgZGF0YSBmb3IgdGhlIGN1cnJlbnQgcG9vbA0KICAgICAgcG9vbF9yZXNpZHVhbHMgPC0gc3Vic2V0X3Jlc2lkdWFsc1tzdWJzZXRfcmVzaWR1YWxzJHBvb2xfaWQgPT0gcG9vbF9pZCwgXQ0KICAgICAgDQogICAgICAgIyBFbnN1cmUgdGhlcmUgaXMgZGF0YSBiZWZvcmUgY2FsY3VsYXRpbmcgdGhlIG1heGltdW0gcmVzaWR1YWwgZGVwdGgNCiAgaWYgKG5yb3cocG9vbF9yZXNpZHVhbHMpID09IDAgfHwgYWxsKGlzLm5hKHBvb2xfcmVzaWR1YWxzJHJlc2lkdWFsX2RlcHRoKSkpIHsNCiAgICBtZXNzYWdlKHBhc3RlKCJTa2lwcGluZyBQb29sOiIsIHBvb2xfaWQsICJTaXRlOiIsIHNpdGUsICJZZWFyOiIsIHllYXIsICItIG5vIHZhbGlkIHJlc2lkdWFsIGRlcHRoIGRhdGEgYXZhaWxhYmxlLiIpKQ0KICAgIG5leHQNCiAgfQ0KICAgICAgIyBDYWxjdWxhdGUgdGhlIG1heGltdW0gcmVzaWR1YWwgZGVwdGgNCiAgICAgIG1heF9yZXNpZHVhbF9kZXB0aCA8LSBtYXgocG9vbF9yZXNpZHVhbHMkcmVzaWR1YWxfZGVwdGgsIG5hLnJtID0gVFJVRSkNCiAgICAgIA0KICAgICAgIyBBcHBseSBzZWxlY3Rpb24gY3JpdGVyaWE6IGVpdGhlciB0aGUgbWF4IHJlc2lkdWFsIGRlcHRoIGlzID49IHNkIG9yIHRoZSBjdXN0b20gdGhyZXNob2xkIGlzIG1ldA0KICAgICAgaWYgKCFpcy5udWxsKGN1c3RvbV9kZXB0aF90aHJlc2hvbGQpKSB7DQogICAgICAgIGlmIChtYXhfcmVzaWR1YWxfZGVwdGggPCBjdXN0b21fZGVwdGhfdGhyZXNob2xkKSB7DQogICAgICAgICAgbmV4dCAgIyBTa2lwIHRoaXMgcG9vbCBpZiBpdCBkb2Vzbid0IG1lZXQgdGhlIGN1c3RvbSB0aHJlc2hvbGQNCiAgICAgICAgfQ0KICAgICAgfSBlbHNlIGlmICh1c2Vfc2RfdGhyZXNob2xkICYmIG1heF9yZXNpZHVhbF9kZXB0aCA8IHNkX3Jlc2lkdWFsX2RlcHRoKSB7DQogICAgICAgIG5leHQgICMgU2tpcCB0aGlzIHBvb2wgaWYgaXQgZG9lc24ndCBtZWV0IHRoZSBTRCB0aHJlc2hvbGQNCiAgICAgIH0NCiAgICAgIA0KICAgICAgIyBJbml0aWFsaXplIGEgY29sdW1uIGZvciBzZWdtZW50IGxlbmd0aHMNCiAgICAgIHBvb2xfcmVzaWR1YWxzJHNlZ21lbnRfbGVuZ3RoIDwtIE5BDQogICAgICANCiAgICAgICMgQ2FsY3VsYXRlIHNlZ21lbnQgbGVuZ3Rocw0KICAgICAgZm9yIChpIGluIDE6bnJvdyhwb29sX3Jlc2lkdWFscykpIHsNCiAgICAgICAgaWYgKGkgPT0gMSkgew0KICAgICAgICAgIHBvb2xfcmVzaWR1YWxzJHNlZ21lbnRfbGVuZ3RoW2ldIDwtIChwb29sX3Jlc2lkdWFscyRkaXN0YW5jZVtpICsgMV0gLSBwb29sX3Jlc2lkdWFscyRkaXN0YW5jZVtpXSkgLyAyDQogICAgICAgIH0gZWxzZSBpZiAoaSA9PSBucm93KHBvb2xfcmVzaWR1YWxzKSkgew0KICAgICAgICAgIHBvb2xfcmVzaWR1YWxzJHNlZ21lbnRfbGVuZ3RoW2ldIDwtIChwb29sX3Jlc2lkdWFscyRkaXN0YW5jZVtpXSAtIHBvb2xfcmVzaWR1YWxzJGRpc3RhbmNlW2kgLSAxXSkgLyAyDQogICAgICAgIH0gZWxzZSB7DQogICAgICAgICAgcG9vbF9yZXNpZHVhbHMkc2VnbWVudF9sZW5ndGhbaV0gPC0gDQogICAgICAgICAgICAoKHBvb2xfcmVzaWR1YWxzJGRpc3RhbmNlW2ldIC0gcG9vbF9yZXNpZHVhbHMkZGlzdGFuY2VbaSAtIDFdKSAvIDIpICsNCiAgICAgICAgICAgICgocG9vbF9yZXNpZHVhbHMkZGlzdGFuY2VbaSArIDFdIC0gcG9vbF9yZXNpZHVhbHMkZGlzdGFuY2VbaV0pIC8gMikNCiAgICAgICAgfQ0KICAgICAgfQ0KICAgICAgDQogICAgICAjIENhbGN1bGF0ZSB0aGUgbGVuZ3RoIG9mIHRoZSBwb29sDQogICAgICBwb29sX2xlbmd0aCA8LSBzdW0ocG9vbF9yZXNpZHVhbHMkc2VnbWVudF9sZW5ndGgsIG5hLnJtID0gVFJVRSkNCiAgICAgIA0KICAgICAgIyBDYWxjdWxhdGUgdGhlIHRvdGFsIGxlbmd0aCB3aXRoIEZpbmVzIGNvbnRhaW5pbmcgInkiIG9yICJ5ZXMiIChjYXNlLWluc2Vuc2l0aXZlKQ0KICAgICAgZmluZXNfbGVuZ3RoIDwtIHN1bSgNCiAgICAgICAgcG9vbF9yZXNpZHVhbHMkc2VnbWVudF9sZW5ndGhbDQogICAgICAgICAgZ3JlcGwoIlxcYih5fHllcylcXGIiLCBwb29sX3Jlc2lkdWFscyRGaW5lcywgaWdub3JlLmNhc2UgPSBUUlVFKQ0KICAgICAgICBdLA0KICAgICAgICBuYS5ybSA9IFRSVUUNCiAgICAgICkNCiAgICAgIA0KICAgICAgIyBDYWxjdWxhdGUgdGhlIHByb3BvcnRpb24NCiAgICAgIGZpbmVzX3Byb3BvcnRpb24gPC0gZmluZXNfbGVuZ3RoIC8gcG9vbF9sZW5ndGgNCiAgICAgIA0KICAgICAgIyBTdG9yZSByZXN1bHRzIGZvciB0aGUgY3VycmVudCBwb29sDQogICAgICBmaW5lc19wcm9wb3J0aW9uX3NpdGVfeWVhcltbYXMuY2hhcmFjdGVyKHBvb2xfaWQpXV0gPC0gbGlzdCgNCiAgICAgICAgcG9vbF9sZW5ndGggPSBwb29sX2xlbmd0aCwNCiAgICAgICAgZmluZXNfbGVuZ3RoID0gZmluZXNfbGVuZ3RoLA0KICAgICAgICBmaW5lc19wcm9wb3J0aW9uID0gZmluZXNfcHJvcG9ydGlvbg0KICAgICAgKQ0KICAgIH0NCiAgICANCiAgICAjIENvbnZlcnQgdGhlIHJlc3VsdHMgaW50byBhIGRhdGFmcmFtZSBmb3IgdGhlIGN1cnJlbnQgU2l0ZS95ZWFyDQogICAgaWYgKGxlbmd0aChmaW5lc19wcm9wb3J0aW9uX3NpdGVfeWVhcikgPiAwKSB7DQogICAgICBwb29sX2lkcyA8LSBuYW1lcyhmaW5lc19wcm9wb3J0aW9uX3NpdGVfeWVhcikNCiAgICAgIGZpbmVzX3Byb3BvcnRpb25fZGYgPC0gZGF0YS5mcmFtZSgNCiAgICAgICAgcG9vbF9pZCA9IHBvb2xfaWRzLA0KICAgICAgICBwb29sX2xlbmd0aCA9IHNhcHBseShmaW5lc19wcm9wb3J0aW9uX3NpdGVfeWVhciwgZnVuY3Rpb24oeCkgeCRwb29sX2xlbmd0aCksDQogICAgICAgIGZpbmVzX2xlbmd0aCA9IHNhcHBseShmaW5lc19wcm9wb3J0aW9uX3NpdGVfeWVhciwgZnVuY3Rpb24oeCkgeCRmaW5lc19sZW5ndGgpLA0KICAgICAgICBmaW5lc19wcm9wb3J0aW9uID0gc2FwcGx5KGZpbmVzX3Byb3BvcnRpb25fc2l0ZV95ZWFyLCBmdW5jdGlvbih4KSB4JGZpbmVzX3Byb3BvcnRpb24pLA0KICAgICAgICBTaXRlID0gc2l0ZSwNCiAgICAgICAgeWVhciA9IHllYXINCiAgICAgICkNCiAgICAgIA0KICAgICAgIyBDYWxjdWxhdGUgb3ZlcmFsbCBzdW1tYXJ5IHN0YXRpc3RpY3MgZm9yIHRoZSBjdXJyZW50IFNpdGUveWVhcg0KICAgICAgdG90YWxfYWxsX3Bvb2xzX2xlbmd0aCA8LSBzdW0oZmluZXNfcHJvcG9ydGlvbl9kZiRwb29sX2xlbmd0aCwgbmEucm0gPSBUUlVFKQ0KICAgICAgdG90YWxfYWxsX2ZpbmVzX2xlbmd0aCA8LSBzdW0oZmluZXNfcHJvcG9ydGlvbl9kZiRmaW5lc19sZW5ndGgsIG5hLnJtID0gVFJVRSkNCiAgICAgIG92ZXJhbGxfZmluZXNfcHJvcG9ydGlvbiA8LSB0b3RhbF9hbGxfZmluZXNfbGVuZ3RoIC8gdG90YWxfYWxsX3Bvb2xzX2xlbmd0aA0KICAgICAgDQogICAgICAjIEFkZCB0aGUgb3ZlcmFsbCBzdW1tYXJ5IGFzIGEgZmluYWwgcm93DQogICAgICBmaW5hbF9yb3cgPC0gZGF0YS5mcmFtZSgNCiAgICAgICAgcG9vbF9pZCA9ICJUb3RhbCIsDQogICAgICAgIHBvb2xfbGVuZ3RoID0gdG90YWxfYWxsX3Bvb2xzX2xlbmd0aCwNCiAgICAgICAgZmluZXNfbGVuZ3RoID0gdG90YWxfYWxsX2ZpbmVzX2xlbmd0aCwNCiAgICAgICAgZmluZXNfcHJvcG9ydGlvbiA9IG92ZXJhbGxfZmluZXNfcHJvcG9ydGlvbiwNCiAgICAgICAgU2l0ZSA9IHNpdGUsDQogICAgICAgIHllYXIgPSB5ZWFyDQogICAgICApDQogICAgICANCiAgICAgICMgQmluZCB0aGUgZmluYWwgcm93IHRvIHRoZSBtYWluIGRhdGFmcmFtZQ0KICAgICAgZmluZXNfcHJvcG9ydGlvbl9kZiA8LSByYmluZChmaW5lc19wcm9wb3J0aW9uX2RmLCBmaW5hbF9yb3cpDQogICAgICANCiAgICAgICMgU3RvcmUgdGhlIHJlc3VsdCBmb3IgdGhlIGN1cnJlbnQgU2l0ZS95ZWFyDQogICAgICBmaW5lc19wcm9wb3J0aW9uX2xpc3RbW3Bhc3RlKHNpdGUsIHllYXIsIHNlcCA9ICJfIildXSA8LSBmaW5lc19wcm9wb3J0aW9uX2RmDQogICAgfQ0KICB9DQogIA0KICAjIENvbWJpbmUgcmVzdWx0cyBmcm9tIGFsbCBTaXRlcyBhbmQgeWVhcnMgaW50byBvbmUgZGF0YWZyYW1lDQogIGNvbWJpbmVkX2ZpbmVzX3Byb3BvcnRpb25fZGYgPC0gZG8uY2FsbChyYmluZCwgZmluZXNfcHJvcG9ydGlvbl9saXN0KQ0KICANCiAgcmV0dXJuKGNvbWJpbmVkX2ZpbmVzX3Byb3BvcnRpb25fZGYpDQp9DQpgYGANCg0KSG93ZXZlciwgc2hvdWxkIGl0IGJlIG9mIGdyZWF0ZXIgaW50ZXJlc3QgZm9yIHlvdXIgcHJvamVjdCwgd2UgaGF2ZSBpbmNsdWRlZCBpbiB0aGUgY29kZSBiZWxvdyB0aGUgYWJpbGl0eSB0byBzZWxlY3QgYSBzdWJzZXQgb2YgcG9vbHMuIENvbnNpc3RlbnQgd2l0aCB0aGUgcHJldmlvdXMgY3VzdG9tIGRlcHRoIHRocmVzaG9sZCwgeW91IGNhbiBhZGQgYSBzcGVjaWZpZWQgZGVwdGggaW4gbWV0cmVzLCBvciBlbnRlciAnTlVMTCcgdG8gc2VsZWN0IG9ubHkgcG9vbHMgd2l0aCBhIG1heGltdW0gcmVzaWR1YWwgZGVwdGggZ3JlYXRlciB0aGFuIHRoZSBzdGFuZGFyZCBkZXZpYXRpb24gb2YgdGhlIHJlc2lkdWFsIGRlcHRocyBmb3IgdGhlIGVudGlyZSBzYW1wbGVkIHJlYWNoLiBPdXIgZGVmYXVsdCBpcyAwIChubyBzdWJzZXR0aW5nKS4NCg0KYGBge3IgZmluZXMgY3VzdG9tIGRlcHRofQ0KIyBEZWZpbmUgY3VzdG9tIHRocmVzaG9sZCBpZiByZXF1aXJlZC4gV2UgcmVjb21tZW5kIDAgKGFsbCByZXNpZHVhbCBwb29scywgcmVnYXJkbGVzcyBvZiBtYXhpbXVtIGRlcHRoKQ0KY3VzdG9tX2RlcHRoIDwtIDAgICMgUmVwbGFjZSB3aXRoIHlvdXIgZGVzaXJlZCB0aHJlc2hvbGQgaW4gbWV0cmVzLCBvciBzZXQgdG8gTlVMTCB0byB1c2UgdGhlIHN0YW5kYXJkIGRldmlhdGlvbiBvZiB0aGUgcmVhY2ggKHRoYXQgeWVhcikNCmBgYA0KDQpgYGB7ciBmaW5lcyB0YWJsZSBkYXRhZnJhbWVzLCBlY2hvID0gRkFMU0V9DQojIENhbGwgdGhlIGNhbGN1bGF0ZV9maW5lc19wcm9wb3J0aW9uIGZ1bmN0aW9uIHdpdGggdGhlIHJlcXVpcmVkIHBhcmFtZXRlcnMNCmZpbmVzX3Byb3BvcnRpb25fcmVzdWx0IDwtIGNhbGN1bGF0ZV9maW5lc19wcm9wb3J0aW9uKA0KICBwb29sX2RhdGEgPSBwb29sX3N1bW1hcnlfcmVzdWx0LCAgICMgDQogIHJlc2lkdWFscy5kZiA9IHJlc2lkdWFscy5kZiwgICAgICAgIyANCiAgY3VzdG9tX2RlcHRoX3RocmVzaG9sZCA9IGN1c3RvbV9kZXB0aCwgICMgVXNlIGN1c3RvbSB0aHJlc2hvbGQgZm9yIGZpbHRlcmluZyAod2lsbCBvdmVyd3JpdGUgTlVMTCAvIFNEIGNhc2UpDQogIHVzZV9zZF90aHJlc2hvbGQgPSBUUlVFICAgICAgICAgICAgIyBUUlVFID0gU0QgaXMgdXNlZCB3aGVuIHRoZXJlIGlzIG5vIGN1c3RvbV9kZXB0aCBzcGVjaWZpZWQuIA0KKQ0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICANCiMgU3BsaXQgdGhlIHJlc3VsdHMgYnkgU2l0ZQ0Kc2l0ZV9zcGxpdCA8LSBzcGxpdChmaW5lc19wcm9wb3J0aW9uX3Jlc3VsdCwgZmluZXNfcHJvcG9ydGlvbl9yZXN1bHQkU2l0ZSkNCg0KIyBDcmVhdGUgYSBuYW1lZCBsaXN0IHRvIHN0b3JlIGVhY2ggc2l0ZSdzIGRhdGENCnNpdGVfZGF0YV9mcmFtZXMgPC0gbGlzdCgpDQoNCiMgTG9vcCB0aHJvdWdoIGVhY2ggc2l0ZSwgc29ydCB0aGUgZGF0YSwgYW5kIGRpc3BsYXkgdGhlIHRhYmxlcw0KZm9yIChzaXRlX25hbWUgaW4gbmFtZXMoc2l0ZV9zcGxpdCkpIHsNCiAgc2l0ZV9kYXRhIDwtIHNpdGVfc3BsaXRbW3NpdGVfbmFtZV1dDQogIA0KICAjIFNlcGFyYXRlIHRoZSAiVG90YWwiIHJvdw0KICB0b3RhbF9yb3cgPC0gc2l0ZV9kYXRhW3NpdGVfZGF0YSRwb29sX2lkID09ICJUb3RhbCIsIF0NCiAgc2l0ZV9kYXRhIDwtIHNpdGVfZGF0YVtzaXRlX2RhdGEkcG9vbF9pZCAhPSAiVG90YWwiLCBdDQogIA0KICAjIENvbnZlcnQgcG9vbF9pZCB0byBudW1lcmljIGZvciBzb3J0aW5nLCBoYW5kbGluZyBub24tbnVtZXJpYyB2YWx1ZXMNCiAgc2l0ZV9kYXRhJHBvb2xfaWRfbnVtZXJpYyA8LSBhcy5udW1lcmljKGFzLmNoYXJhY3RlcihzaXRlX2RhdGEkcG9vbF9pZCkpDQogIA0KICAjIFNvcnQgYnkgeWVhciBhbmQgcG9vbF9pZF9udW1lcmljDQogIHNpdGVfZGF0YSA8LSBzaXRlX2RhdGFbb3JkZXIoc2l0ZV9kYXRhJHllYXIsIHNpdGVfZGF0YSRwb29sX2lkX251bWVyaWMpLCBdDQogIA0KICAjIERyb3AgdGhlIHRlbXBvcmFyeSBudW1lcmljIGNvbHVtbg0KICBzaXRlX2RhdGEkcG9vbF9pZF9udW1lcmljIDwtIE5VTEwNCiAgDQogICMgRW5zdXJlIHRoZSAiVG90YWwiIHJvdyBoYXMgdGhlIHNhbWUgY29sdW1ucyBhcyBzaXRlX2RhdGENCiAgdG90YWxfcm93IDwtIHRvdGFsX3Jvd1ssIG5hbWVzKHNpdGVfZGF0YSksIGRyb3AgPSBGQUxTRV0NCiAgDQogICMgUmVhdHRhY2ggdGhlICJUb3RhbCIgcm93IGF0IHRoZSBib3R0b20NCiAgc29ydGVkX3NpdGVfZGF0YSA8LSByYmluZChzaXRlX2RhdGEsIHRvdGFsX3JvdykNCiAgDQogICMgTW92ZSBTaXRlIGFuZCB5ZWFyIGNvbHVtbnMgdG8gdGhlIGxlZnQgYW5kIGZvcm1hdCB0aGUgZGF0YXRhYmxlDQogIHNvcnRlZF9zaXRlX2RhdGEgPC0gc29ydGVkX3NpdGVfZGF0YSAlPiUNCiAgICBzZWxlY3QoU2l0ZSwgeWVhciwgZXZlcnl0aGluZygpKSAgIyBNb3ZlIFNpdGUgYW5kIHllYXIgdG8gdGhlIGxlZnQNCiAgDQojIFJlbW92ZSByb3cgbmFtZXMgZnJvbSB0aGUgZGF0YSBmcmFtZSBleHBsaWNpdGx5DQogIHJvd25hbWVzKHNvcnRlZF9zaXRlX2RhdGEpIDwtIE5VTEwNCiAgDQogIyBTdG9yZSB0aGUgY2xlYW5lZCBkYXRhIGluIHRoZSBsaXN0DQogIHNpdGVfZGF0YV9mcmFtZXNbW3NpdGVfbmFtZV1dIDwtIHNvcnRlZF9zaXRlX2RhdGENCn0NCmBgYA0KDQpgYGB7ciBjcmVhdGUgdGFibGVzLCBlY2hvID0gRkFMU0UsIHJlc3VsdHM9J2FzaXMnfQ0KZm9yIChzaXRlX25hbWUgaW4gbmFtZXMoc2l0ZV9kYXRhX2ZyYW1lcykpIHsNCiAgIyBQcmVwYXJlIGdlbmVyaWMgZmlsZSBuYW1lIGZvciBleHBvcnQNCiAgZmlsZW5hbWUgPC0gcGFzdGUwKHNpdGVfbmFtZSwgIl9wb29sX2ZpbmVzLmNzdiIpICAjIC5jc3YgZXh0ZW5zaW9uDQogIA0KICAjIEV4cG9ydCB0aGUgdGFibGUgYXMgLmNzdg0KICBleHBvcnRfdGFibGUoc2l0ZV9kYXRhX2ZyYW1lc1tbc2l0ZV9uYW1lXV0sIGZpbGVuYW1lKQ0KICANCiAgI3ByaW50IHRhYmxlIGluIFINCiAgY2F0KCJcbiIpDQogIHByaW50KA0KICAgIGthYmxlKHNpdGVfZGF0YV9mcmFtZXNbW3NpdGVfbmFtZV1dLCANCiAgICAgICAgICBjYXB0aW9uID0gcGFzdGUoc2l0ZV9uYW1lLCAiLSBQb29sIEZpbmUgU2VkaW1lbnQiKSwgDQogICAgICAgICAgZm9ybWF0ID0gImh0bWwiLCBhbGlnbiA9ICJjIiwgZGlnaXRzID0gMykgJT4lDQogICAgICBrYWJsZV9zdHlsaW5nKGJvb3RzdHJhcF9vcHRpb25zID0gYygic3RyaXBlZCIsICJob3ZlciIpLCBmdWxsX3dpZHRoID0gRkFMU0UpDQogICkNCiAgY2F0KCJcbiIpDQp9DQoNCiMgRXhwb3J0IHRhYmxlIG9jY3VycyB3aXRoaW4gZnVuY3Rpb24gYWJvdmUNCmBgYA0KDQpUaGUgYWJvdmUgdGFibGVzIChhbHNvIGV4cG9ydGVkIHRvIG91dHB1dCBmb2xkZXIpIGluY2x1ZGUgYSBmaW5hbCByb3cgZm9yIGVhY2ggc2l0ZS15ZWFyIHdpdGggcmVhY2ggdG90YWwgcG9vbCBsZW5ndGgsIHJlYWNoIHRvdGFsIHBvb2wgbGVuZ3RoIHdpdGggZmluZSBzZWRpbWVudCwgYW5kIHRoZSByZWFjaHdpZGUgcHJvcG9ydGlvbiBvZiBwb29scyB3aXRoIGZpbmVzIChhIHJhdGlvIGZyb20gMCB0byAxKS4gQ29tcGFyaXNvbiBvZiB0aGUgcmVhY2h3aWRlIHByb3BvcnRpb24gYWxvbmUgbWF5IGJlIHN1ZmZpY2llbnQgdG8gZGVtb25zdHJhdGUgcHJvamVjdCBlZmZlY3RpdmVuZXNzLCBwZXJoYXBzIGNvbXBsZW1lbnRlZCB3aXRoIHRoZSBmaWd1cmUgdGhhdCB3ZSB3aWxsIGNyZWF0ZSBiZWxvdy4gSG93ZXZlciwgaWYgeW91IHdvdWxkIGxpa2UgdG8gc3RhdGlzdGljYWxseSBjb21wYXJlIGhvdyBmaW5lIHNlZGltZW50IGNoYW5nZWQgb3ZlciB0aW1lIGNvbXBhcmVkIHdpdGggYSBjb250cm9sLCB3ZSBjYW4gbG9vayBhdCB0aGUgZGlzdHJpYnV0aW9ucyBvZiB1bmRlcmx5aW5nIHBvb2wgZGF0YSAodGhlIGZpbmVzX3Byb3BvcnRpb24gZGF0YSBmb3IgZXZlcnkgcG9vbCkuDQoNCiMjIEluZmVyZW50aWFsIFRlc3RzIC0gRmluZXMNCg0KVGhpcyB0aW1lLCB3ZSBhcmUgZGVhbGluZyB3aXRoIGRhdGEgdGhhdCBhcmUgYm91bmRlZCBieSAwIGFuZCAxLiBBbmQgaW4gbWFueSBjYXNlcywgd2UgYWxzbyBhbnRpY2lwYXRlIGEgcmVsYXRpdmVseSBoaWdoIGZyZXF1ZW5jeSBvZiAwcyAobm8gZmluZXMgaW4gcG9vbHMpIGFuZC9vciAxcyAoZmluZXMgdGhyb3VnaG91dCkuIFdlIGFyZSBjb25maWRlbnQgdGhhdCBub24tdHJhbnNmb3JtZWQgZGF0YSB3b3VsZCB2aW9sYXRlIHRoZSBhc3N1bXB0aW9ucyBvZiBBTk9WQSwgc28gd2Ugb21pdCB0aGUgaW5pdGlhbCBkaWFnbm9zdGljIHRlc3RzLiBPdXIgYXR0ZW1wdHMgdG8gYXJjc2luZS10cmFuc2Zvcm0gdGhlIGRhdGEgd2VyZSBub3Qgc3VjY2Vzc2Z1bCwgYXMgb3VyIHRyYW5zZm9ybWVkIGRhdGEgcmVtYWluZWQgbm9uLW5vcm1hbGx5IGRpc3RyaWJ1dGVkIHdpdGggc2lnbmlmaWNhbnQgaGV0ZXJvc2NlZGFzdGljaXR5LiBBcyBzdWNoLCBhbmQgc2luY2Ugd2Ugc3VzcGVjdCBvdXIgZmluZXMgZGF0YSBkaXN0cmlidXRpb24gaXMgbm90IHBhcnRpY3VsYXJseSB1bnVzdWFsLCB3ZSBvcHRlZCBmb3IgQmV0YSByZWdyZXNzaW9uLg0KDQo8ZGl2IHN0eWxlPSJib3JkZXI6IDFweCBzb2xpZCAjZGRkOyBwYWRkaW5nOiAxMHB4OyBtYXJnaW46IDEwcHggMDsgYmFja2dyb3VuZC1jb2xvcjogI2Y5ZjlmOTsgZm9udC1zaXplOiBzbWFsbGVyOyI+DQpTbGlnaHRseSBuZXJkeSBiaXQsIGZlZWwgZnJlZSB0byBpZ25vcmU6IEJldGEgcmVncmVzc2lvbnMgYXJlIGNhcGFibGUgb2YgZGVhbGluZyB3aXRoIG5vbi1ub3JtYWwgaGV0ZXJvc2NlZGFzdGljIGRhdGEuIEFsdGhvdWdoIHRoZXkgY2Fubm90IGFjdHVhbGx5IGhhbmRsZSAwJ3MgYW5kIDEncywgZm9yIG91ciBjYXNlIHRoZXkgYXJlIHByZWZlcmFibGUgb3ZlciB0d28tcGFydCBtb2RlbHMgKGUuZy4gaHVyZGxlIG1vZGVscyk6IFNpbmNlIGFuIG9ic2VydmF0aW9uIG9mICJubyBmaW5lIHNlZGltZW50IiBjb3VsZCB2ZXJ5IHBsYXVzaWJseSBiZSByZWNvcmRlZCB3aGVyZSAyIGNtIG9mIGZpbmUgc2VkaW1lbnQgd2FzIGFjdHVhbGx5IHByZXNlbnQgaW4gYSAyMCBtIHBvb2wsIHdlIGFyZSBjb21mb3J0YWJsZSBhZGp1c3RpbmcgdGhlIDAncyBhbmQgMSdzIHRvIDAuMDAxIGFuZCAwLjk5OS4gV2UgZmVlbCBhIGh1cmRsZSBtb2RlbCB3b3VsZCBleGNlc3NpdmVseSBjb21wbGljYXRlIGludGVycHJldGFiaWxpdHkgKGUuZy4gYSBiaW5vbWlhbCBmaW5lcyBwcmVzZW5jZS9hYnNlbmNlIG1lY2hhbmlzbSBwbHVzIGEgZmluZXMgcXVhbnRpdHkgbWVjaGFuaXNtKS4gU2VlIEdlaXNzaW5nZXIgZXQgYWwgMjAyMiBpZiBpbnRlcmVzdGVkLg0KPC9kaXY+DQoNCldlIHdpbGwgZ2VuZXJhdGUgYSBmcmVxdWVuY3kgcGxvdCBvZiB0aGUgZmluZSBwcm9wb3J0aW9uIGRhdGEsIGZpdCB0aGUgQmV0YSByZWdyZXNzaW9uLCBhbmQgcGxvdCB0aGUgZnJlcXVlbmN5IGRpc3RyaWJ1dGlvbiBvZiB0aGUgcmVzaWR1YWxzICh3aGljaCBzaG91bGQgYmUgYnJvYWRseSBzeW1tZXRyaWNhbCBhcm91bmQgemVybykgYW5kIHRoZWlyIHJlbGF0aW9uc2hpcHMgdG8gdGhlIGZpdHRlZCB2YWx1ZXMgKGZvciB3aGljaCBubyBjbGVhciByZWxhdGlvbnNoaXAgb3IgaGV0ZXJvc2NlZGFzdGljaXR5IHNob3VsZCBiZSBldmlkZW50KS4gV2Ugd2lsbCBvbmx5IGV4cG9ydCB0aGUgcmVzdWx0cyBvZiB0aGUgQmV0YSByZWdyZXNzaW9uIHRvIHlvdXIgb3V0cHV0IGZvbGRlci4NCg0KYGBge3IgZmluZXMgZGF0YSBldmFsdWF0aW5nLCBlY2hvID0gRkFMU0V9DQojIyMjIGFkZCB0aGUgYmVmb3JlL2FmdGVyIGNhdGVnb3JpZXMgZnJvbSBwcmV2aW91cyBpbnB1dA0KZmluZXNfcHJvcG9ydGlvbl9yZXN1bHQgPC0gZmluZXNfcHJvcG9ydGlvbl9yZXN1bHQgJT4lDQogIG11dGF0ZShUaW1lX0NhdGVnb3J5ID0gY2FzZV93aGVuKA0KICAgIHllYXIgJWluJSBiZWZvcmVfeWVhcnMgfiAiQmVmb3JlIiwNCiAgICB5ZWFyICVpbiUgYWZ0ZXJfeWVhcnMgfiAiQWZ0ZXIiLA0KICAgIFRSVUUgfiBOQV9jaGFyYWN0ZXJfDQogICkpDQoNCiMgRmlsdGVyIG91dCBzaXRlcyB3aXRob3V0IGJvdGggdGltZSBjYXRlZ29yaWVzLiBSZW1vdmUgcm93cyB3aXRoIHBvb2xfaWQgPSAiVG90YWwiDQpmaW5lc19wcm9wb3J0aW9uX2ZpbHRlcmVkIDwtIGZpbmVzX3Byb3BvcnRpb25fcmVzdWx0ICU+JQ0KICBmaWx0ZXIocG9vbF9pZCAhPSAiVG90YWwiKSAlPiUNCiAgZ3JvdXBfYnkoU2l0ZSkgJT4lDQogIGZpbHRlcihhbGwoYygiQmVmb3JlIiwgIkFmdGVyIikgJWluJSBUaW1lX0NhdGVnb3J5KSkgJT4lDQogIHVuZ3JvdXAoKQ0KDQojIEFkanVzdCB2YWx1ZXMgb2YgZXhhY3RseSAwIG9yIDEgKGlmIGFueSkNCmZpbmVzX3Byb3BvcnRpb25fZmlsdGVyZWQgPC0gZmluZXNfcHJvcG9ydGlvbl9maWx0ZXJlZCAlPiUNCiAgbXV0YXRlKGZpbmVzX3Byb3BvcnRpb25fYWRqdXN0ZWQgPSBjYXNlX3doZW4oDQogICAgZmluZXNfcHJvcG9ydGlvbiA9PSAwIH4gMC4wMDEsICAjIFNsaWdodGx5IGFkanVzdCAwDQogICAgZmluZXNfcHJvcG9ydGlvbiA9PSAxIH4gMC45OTksICAjIFNsaWdodGx5IGFkanVzdCAxDQogICAgVFJVRSB+IGZpbmVzX3Byb3BvcnRpb24gICAgICAgICAjIEtlZXAgb3RoZXIgdmFsdWVzIGFzIGlzDQogICkpDQoNCiMgU3RlcCAyOiBWaXN1YWxpemUgdGhlIGRpc3RyaWJ1dGlvbiBvZiBmaW5lc19wcm9wb3J0aW9uDQpnZ3Bsb3QoZmluZXNfcHJvcG9ydGlvbl9maWx0ZXJlZCwgYWVzKHggPSBmaW5lc19wcm9wb3J0aW9uX2FkanVzdGVkKSkgKw0KICBnZW9tX2hpc3RvZ3JhbShiaW5zID0gMzAsIGZpbGwgPSAiYmx1ZSIsIGFscGhhID0gMC43KSArDQogIGdlb21fZGVuc2l0eShjb2xvciA9ICJyZWQiLCBsaW5ld2lkdGggPSAxKSArDQogIGxhYnModGl0bGUgPSAiRGlzdHJpYnV0aW9uIG9mIEZpbmVzIFByb3BvcnRpb24gKEFkanVzdGVkKSIsDQogICAgICAgeCA9ICJGaW5lcyBQcm9wb3J0aW9uIChBZGp1c3RlZCkiLCB5ID0gIkZyZXF1ZW5jeSIpICsNCiAgdGhlbWVfbWluaW1hbCgpDQoNCiMgU3RlcCAzOiBGaXQgYSBCZXRhIHJlZ3Jlc3Npb24gbW9kZWwNCiMgSW5jbHVkZSBTaXRlLCBZZWFyLCBhbmQgVGltZV9DYXRlZ29yeSBpbiB0aGUgZm9ybXVsYQ0KYmV0YV9tb2RlbCA8LSBiZXRhcmVnKGZpbmVzX3Byb3BvcnRpb25fYWRqdXN0ZWQgfiBTaXRlICogVGltZV9DYXRlZ29yeSwNCiAgICAgICAgICAgICAgICAgICAgICBkYXRhID0gZmluZXNfcHJvcG9ydGlvbl9maWx0ZXJlZCkNCg0KIyBTdGVwIDQ6IEFzc2VzcyBtb2RlbCBkaWFnbm9zdGljcw0KDQojIENoZWNrIHJlc2lkdWFscw0KZmluZXNfcHJvcG9ydGlvbl9maWx0ZXJlZCRyZXNpZHVhbHMgPC0gcmVzaWR1YWxzKGJldGFfbW9kZWwsIHR5cGUgPSAicGVhcnNvbiIpDQpnZ3Bsb3QoZmluZXNfcHJvcG9ydGlvbl9maWx0ZXJlZCwgYWVzKHggPSByZXNpZHVhbHMpKSArDQogIGdlb21faGlzdG9ncmFtKGJpbnMgPSAzMCwgZmlsbCA9ICJibHVlIiwgYWxwaGEgPSAwLjcpICsNCiAgZ2VvbV9kZW5zaXR5KGNvbG9yID0gInJlZCIsIGxpbmV3aWR0aCA9IDEpICsNCiAgbGFicyh0aXRsZSA9ICJEaXN0cmlidXRpb24gb2YgUmVzaWR1YWxzIiwgeCA9ICJSZXNpZHVhbHMiLCB5ID0gIkZyZXF1ZW5jeSIpICsNCiAgdGhlbWVfbWluaW1hbCgpDQoNCiMgUGxvdCBmaXR0ZWQgdnMgcmVzaWR1YWxzDQpmaW5lc19wcm9wb3J0aW9uX2ZpbHRlcmVkJGZpdHRlZCA8LSBmaXR0ZWQoYmV0YV9tb2RlbCkNCmdncGxvdChmaW5lc19wcm9wb3J0aW9uX2ZpbHRlcmVkLCBhZXMoeCA9IGZpdHRlZCwgeSA9IHJlc2lkdWFscykpICsNCiAgZ2VvbV9wb2ludChhbHBoYSA9IDAuNSkgKw0KICBnZW9tX2hsaW5lKHlpbnRlcmNlcHQgPSAwLCBsaW5ldHlwZSA9ICJkYXNoZWQiLCBjb2xvciA9ICJyZWQiKSArDQogIGxhYnModGl0bGUgPSAiRml0dGVkIHZzIFJlc2lkdWFscyIsIHggPSAiRml0dGVkIFZhbHVlcyIsIHkgPSAiUmVzaWR1YWxzIikgKw0KICB0aGVtZV9taW5pbWFsKCkNCg0KIyBTdW1tYXJ5IG9mIHRoZSBtb2RlbA0Kc3VtbWFyeShiZXRhX21vZGVsKQ0KDQojIEV4cG9ydCB0ZXN0IFN1bW1hcnkNCnN1bW1hcnlfdGV4dCA8LSBjYXB0dXJlLm91dHB1dChzdW1tYXJ5KGJldGFfbW9kZWwpKQ0KZXhwb3J0X3N1bW1hcnkoc3VtbWFyeV90ZXh0LCAiQmV0YSBSZWdyZXNzaW9uIG9mIEZpbmVzIGluIFBvb2xzIikNCmBgYA0KDQpTaW5jZSB5b3UgbWF5IG5vdCBiZSBmYW1pbGlhciB3aXRoIEJldGEgcmVncmVzc2lvbiwgaGVyZSBhcmUgc29tZSBiYXNpY3Mgb24gaW50ZXJwcmV0YXRpb24gZm9yIHRoZSB0ZXN0IG91dHB1dDoNCg0KLSAiT3B0aW1pemF0aW9uIGZhaWxlZCB0byBjb252ZXJnZS4uLiIgSWYgeW91IHNlZSB0aGlzIHdhcm5pbmcsIGl0IG1heSBiZSB0aGF0IHRoZXJlIHdlcmUgMCB2YWx1ZXMgYWNyb3NzIGFuIGVudGlyZSBTaXRlLiBUaGlzIHNob3VsZCBiZSBmYWlybHkgZWFzeSB0byBpbnRlcnByZXQgd2l0aG91dCBpbmZlcmVudGlhbCB0ZXN0cy4NCg0KLSBRdWFudGlsZSByZXNpZHVhbHMgbWVhc3VyZSB0aGUgZGlmZmVyZW5jZSBiZXR3ZWVuIHRoZSBhY3R1YWwgZGF0YSBhbmQgcHJlZGljdGVkIHZhbHVlcy4gVGhlIG1lZGlhbiBzaG91bGQgYmUgY2xvc2UgdG8gMC4gQWxzbyBjaGVjayB0aGUgcmVzaWR1YWxzIHZzIGZpdHRlZCBwbG90IHRvIGVuc3VyZSB0aGVyZSBpcyBubyBjbGVhciB0cmVuZCBvciB1bnVzdWFsIG91dGxpZXJzDQoNCi0gQ29lZmZpY2llbnRzIChtZWFuIG1vZGVsKTogdGhlc2UgYXJlIHRoZSBlZmZlY3RzIG9mIHRoZSBwcmVkaWN0b3JzIChzaXRlLCB0aW1lKSBvbiB0aGUgcmVzcG9uc2UgdmFyaWFibGUgKGZpbmUgc2VkaW1lbnQgcHJvcG9ydGlvbiBpbiBwb29scykuICoqTG9vayBmb3Igc2lnbmlmaWNhbnQgcCB2YWx1ZXMgaW4gdGhlIGxhc3QgY29sdW1uLCBwYXJ0aWN1bGFybHkgZm9yIHRoZSBTaXRlXF9cX1xfXF9cX1w6VGltZVxfQ2F0ZWdvcnlcX1xfXF9cX1xfIHJvdywgd2hpY2ggaXMgdGhlIGludGVyYWN0aW9uIHRlcm0gKGlmIHNpZ25pZmljYW50LCB0aGlzIG1lYW5zIHRoZSBwcm9wb3J0aW9uIG9mIGZpbmVzIGluIHJlc2lkdWFsIHBvb2xzIGNoYW5nZWQgb3ZlciB0aW1lIGRpZmZlcmVudGx5IGJldHdlZW4gc2l0ZXMpKiouIA0KDQotIFBoaSBjb2VmZmljaWVudHM6IHRoZXJlIGlzIGEgcC12YWx1ZSBoZXJlIGFzIHdlbGwsIGJ1dCB0aGlzIHJlZmVycyB0byB3aGV0aGVyIHRoZSBzcHJlYWQgb2YgdGhlIGRhdGEgYXJvdW5kIHRoZSBtZWFuIHdhcyBhbiBpbXBvcnRhbnQgZmVhdHVyZS4gSWYgdGhlIHBoaSBlc3RpbWF0ZSBpcyB2ZXJ5IGhpZ2gsIHRoaXMgbWVhbnMgdGhlIGRhdGEgd2FzIGNvbmNlbnRyYXRlZCBhcm91bmQgdGhlIG1lYW4gKGZpbmVzIHByb3BvcnRpb24gZG9lc24ndCBmbHVjdHVhdGUgbXVjaCBiZXR3ZWVuIHNpdGVzL3RpbWVzKS4gQ29uc2lkZXIgcGhpIG9mIDAuMSB0byBiZSBzcHJlYWQgb3V0IGRhdGEsIDEgdG8gYmUgbW9kZXJhdGUsIGFuZCAxMCB0byBiZSBjb25jZW50cmF0ZWQgYXJvdW5kIHRoZSBtZWFuLg0KDQotIFBzZXVkbyBSLXNxdWFyZWQ6IHRoaXMgaXMgaG93IG11Y2ggb2YgdGhlIHZhcmlhdGlvbiBpbiBmaW5lcyBpbiBwb29scyBjYW4gYmUgZXhwbGFpbmVkIGJ5IHRoZSBzaXRlIGFuZCB0aW1lIHZhcmlhYmxlcy4gT2Z0ZW4gbG93IGluIGVjb2xvZ2ljYWwgY29udGV4dHMuDQoNClByb3BvcnRpb25hbCBkYXRhIGNhbiBiZSBsZXNzIGludHVpdGl2ZSB0byBpbnRlcnByZXQsIGFuZCB1c2luZyBhbiB1bmZhbWlsaWFyIGluZmVyZW50aWFsIHRlc3QgbWlnaHQgbm90IGNsZWFyIHRoaW5ncyB1cC4gTm90IHRvIHdvcnJ5OiBBZnRlciB3ZSBwZXJmb3JtIGEgc2ltaWxhciBhbmFseXNpcyB3aXRoIHRoZSBhcXVhdGljIHZlZ2V0YXRpb24gZGF0YSwgd2Ugd2lsbCBjcmVhdGUgc29tZSBwbG90cyB0aGF0IHNob3cgdGhlIGRpc3RyaWJ1dGlvbiBvZiBmaW5lcyBhbmQgYXF1YXRpY3MgYWNyb3NzIHRoZSByZWFjaC4gVGhlc2UgcGxvdHMgYXJlIG1vcmUgaW50dWl0aXZlIGFuZCB3aWxsIGhlbHAgeW91IHRvIGludGVycHJldCBhbnkgY2hhbmdlcyBpbiBncmVhdGVyIGNvbnRleHQuIA0KDQojIEFxdWF0aWMgVmVnZXRhdGlvbiBpbiBQb29scw0KDQpJbiB0aGUgZmllbGQsIHlvdSBtYXkgaGF2ZSBhbHNvIGVzdGltYXRlZCB0aGUgcHJvcG9ydGlvbiBvZiB0aGUgd2V0dGVkIHdpZHRoIHRoYXQgd2FzIG9jY3VwaWVkIGJ5IGFxdWF0aWMgdmVnZXRhdGlvbi4gRHVyaW5nIGRhdGEgd3JhbmdsaW5nIHdlIGFkZGVkIHRocmVlIG5ldyBkYXRhIGNvbHVtbnMgdG8gZmFjaWxpdGF0ZSBhbmFseXNlcyBvZiB0aGVzZSBhcXVhdGljIHZlZ2V0YXRpb24gb2JzZXJ2YXRpb25zOiBzdWJ2ZWcgKHN1Ym1lcmdlZCB2ZWdldGF0aW9uKSwgZmxvYXR2ZWcgKGZsb2F0aW5nIHZlZ2V0YXRpb24pLCBhbmQgZW1lcmd2ZWcgKGVtZXJnZW50IHZlZ2V0YXRpb24pLiBXZSB3aWxsIHVzZSB0aGVzZSB2YXJpYWJsZXMgdG8gZXN0aW1hdGUgdGhlIGxlbmd0aCBhbmQgcGxhbiBhcmVhIG9mIGVhY2ggcmVzaWR1YWwgcG9vbCB0aGF0IHdvdWxkIGJlIG9jY3VwaWVkIGJ5IGFxdWF0aWMgdmVnZXRhdGlvbiB3aGVuIGZsb3dzIGFwcHJvYWNoIHplcm8uIFRoZXNlIGNhbiBiZSB1c2VmdWwgbWV0cmljcyBmb3IgdHJhY2tpbmcgaGFiaXRhdCBxdWFsaXR5IGFuZCBtZWNoYW5pc21zIG9mIGhhYml0YXQgY2hhbmdlLCBob3dldmVyIHBsYW4gYXJlYSBlc3RpbWF0ZXMgY29tZSB3aXRoIGEgY2F2ZWF0Og0KDQo8c3BhbiBzdHlsZT0iZm9udC1zaXplOiBzbWFsbGVyOyBtYXJnaW4tbGVmdDogMjBweDsgZGlzcGxheTogYmxvY2s7Ij4NCkluIGVzdGltYXRpbmcgcGxhbiBhcmVhcyBvZiB2ZWdldGF0aW9uLCB3ZSBhc3N1bWUgdGhhdCB0aGUgcHJvcG9ydGlvbiBvZiByZXNpZHVhbCBwb29sIHdpZHRoIG9jY3VwaWVkIGJ5IHZlZ2V0YXRpb24gaXMgZXF1YWwgdG8gdGhlIHByb3BvcnRpb24gb2YgdGhlIHdldHRlZCB3aWR0aCB0aGF0IHdhcyBvY2N1cGllZCBpbiB0aGUgZmllbGQuIEluIG1vc3QgY2FzZXMgdGhpcyB3aWxsIGJlIGFuIG92ZXJlc3RpbWF0ZSBiZWNhdXNlIHRoZSB0aGFsd2VnIHdpbGwgdHlwaWNhbGx5IGhhdmUgbGVzcyB2ZWdldGF0aW9uIGFuZCwgYXMgZmxvd3MgcmVjZWRlLCB0aGUgdGhhbHdlZyBtYWtlcyB1cCBhIGdyZWF0ZXIgcHJvcG9ydGlvbiBvZiB0aGUgd2V0dGVkIHdpZHRoLiBBbHRob3VnaCB2ZWdldGF0ZWQgcmVzaWR1YWwgcG9vbCBhcmVhcyBjYW4gYmUgdXNlZnVsIGZvciB0cmFja2luZyBjaGFuZ2VzIG92ZXIgdGltZSwgYmVjYXVzZSB0aGV5IGFyZSBiYXNlZCBvbiBwcm9wb3J0aW9ucyBvZiB3ZXR0ZWQgd2lkdGhzLCB5b3Ugc2hvdWxkIG5vdCBjb25zaWRlciB0aGVtIGZsb3ctaW5kZXBlbmRlbnQuIFdoZW4gaW50ZXJwcmV0aW5nIGNoYW5nZXMgb3ZlciB0aW1lIChvciBmcm9tIGRpZmZlcmVudCByZWFjaGVzKSwgcmVtZW1iZXIgdGhhdCBpZiBmbG93cyB3ZXJlIG5vdGFibHkgZGlmZmVyZW50LCB0aGVuIHRoZSBhbW91bnQgb2Ygc3VibWVyZ2VkIHZlZ2V0YXRpb24gY2FuIGRpZmZlci4gSWYgeW91IGhhZCB0aGUgdGltZS9hYmlsaXR5IHRvIGNvbGxlY3Qgd2V0dGVkIHdpZHRoIG1lYXN1cmVtZW50cyBhdCBlYWNoIGludGVydmFsIHRoaXMgY291bGQgYmUgdXNlZCB0byBjb250cm9sIGZvciB0aGlzIHZhcmlhdGlvbiBieSBhZGRpbmcgaXQgYXMgYSBjb3ZhcmlhdGUgaW4gdGhlIGluZmVyZW50aWFsIHRlc3QuIE90aGVyd2lzZSwgaW50ZXJwcmV0IHdpdGggY2F1dGlvbi4NCjwvc3Bhbj4NCg0KQXNpZGUgZnJvbSB0aGUgYWJvdmUsIGluIHNvbWUgY2FzZXMgaXQgY2FuIGFsc28gYmUgZGlmZmljdWx0IHRvIGFzc2lnbiBwcm9wb3J0aW9ucyBjb25zaXN0ZW50bHkgaW4gdGhlIGZpZWxkLCBzdWNoIGFzIHdoZW4gaW52YXNpdmUgcmVlZCBjYW5hcnlncmFzIGZvcm1zIGRlbnNlIG1hdHMgdGhhdCBvYnNjdXJlIGJhbmtzIGFuZCB1bmRlcmx5aW5nIHNvaWxzL3N1YnN0cmF0ZXMuIElmIHRoZXJlIHdlcmUgc3VjaCBkaWZmaWN1bHRpZXMgaW4gdGhlIGZpZWxkLCB0aGVzZSBzaG91bGQgYmUgY2xlYXJseSBzdGF0ZWQgdG8gYWlkZSBpbnRlcnByZXRhdGlvbi4gRm9yIHRoZSBwdXJwb3NlcyBvZiBpbnRlcnByZXRhdGlvbiwgcmVtZW1iZXIgdGhhdCBpbiB0aGlzIHNlY3Rpb24gd2UgYXJlIGNvbnNpZGVyaW5nIHRoZSBwcm9wb3J0aW9ucyBvZiB0aGUgbGVuZ3RoIGFuZCB0aGUgYXJlYSBvZiAqcmVzaWR1YWwgcG9vbHMqIHRoYXQgYXJlIG9jY3VwaWVkIGJ5IGFxdWF0aWMgdmVnZXRhdGlvbi4gQXMgc3VjaCwgdGhlIGZpZWxkIG9ic2VydmF0aW9ucyBzaG91bGQgcmVsYXRlIHRvIHByb3BvcnRpb25zIG9mIHdldHRlZCB3aWR0aCAobm90IGJhbmtmdWxsKSwgYmVjYXVzZSBhdCBmbG93cyBhcHByb2FjaGluZyB6ZXJvIHRoZSB2ZWdldGF0aW9uIGJldHdlZW4gb2JzZXJ2ZWQgd2V0dGVkIHdpZHRoIGFuZCBiYW5rZnVsbCB3aWR0aCB3b3VsZCBub3Qgb2NjdXB5IGFueSBwYXJ0IG9mIHRoZSByZXNpZHVhbCBwb29sLiANCg0K8J+Mv/CfjL/wn4y/8J+Mv/CfjL8g8J+Mv/CfjL/wn4y/8J+Mv/CfjL8g8J+Mv/CfjL/wn4y/8J+Mv/CfjL8g8J+Mv/CfjL/wn4y/8J+Mv/CfjL8g8J+Mv/CfjL/wn4y/8J+Mv/CfjL8g8J+Mv/CfjL/wn4y/8J+Mv/CfjL8g8J+Mv/CfjL/wn4y/8J+Mv/CfjL8g8J+Mv/CfjL/wn4y/8J+Mv/CfjL8g8J+Mv/CfjL/wn4y/8J+Mv/CfjL8NCg0KYGBge3IgYXF1YXRpYyB2ZWcgaW4gcG9vbHMsIGVjaG8gPSBGQUxTRX0NCmNhbGN1bGF0ZV92ZWdfcHJvcG9ydGlvbiA8LSBmdW5jdGlvbihyZXNpZHVhbHMuZGYsIHZlZ19jb2x1bW4sIGN1c3RvbV9kZXB0aCA9IE5VTEwpIHsNCiAgIyBWYWxpZGF0ZSB0aGF0IHRoZSB2ZWdldGF0aW9uIGNvbHVtbiBleGlzdHMgaW4gdGhlIHJlc2lkdWFscyBkYXRhZnJhbWUNCiAgaWYgKCF2ZWdfY29sdW1uICVpbiUgY29sbmFtZXMocmVzaWR1YWxzLmRmKSkgew0KICAgIHN0b3AocGFzdGUoIlRoZSBjb2x1bW4iLCB2ZWdfY29sdW1uLCAiaXMgbm90IHByZXNlbnQgaW4gdGhlIHJlc2lkdWFscyBkYXRhZnJhbWUuIikpDQogIH0NCiAgDQogICMgSW5pdGlhbGl6ZSBhIGxpc3QgdG8gc3RvcmUgcmVzdWx0cw0KICB2ZWdfcHJvcG9ydGlvbl9saXN0IDwtIGxpc3QoKQ0KICANCiAgIyBJdGVyYXRlIG92ZXIgZWFjaCB1bmlxdWUgY29tYmluYXRpb24gb2YgU2l0ZSBhbmQgWWVhcg0KICB1bmlxdWVfc2l0ZXNfeWVhcnMgPC0gdW5pcXVlKHJlc2lkdWFscy5kZltjKCJTaXRlIiwgInllYXIiKV0pDQogIA0KZm9yIChpIGluIDE6bnJvdyh1bmlxdWVfc2l0ZXNfeWVhcnMpKSB7DQogIHNpdGUgPC0gdW5pcXVlX3NpdGVzX3llYXJzJFNpdGVbaV0NCiAgeWVhciA8LSB1bmlxdWVfc2l0ZXNfeWVhcnMkeWVhcltpXQ0KICANCiAgIyBTdWJzZXQgdGhlIHJlc2lkdWFscyBkYXRhZnJhbWUgZm9yIHRoZSBjdXJyZW50IFNpdGUgYW5kIFllYXINCiAgc3Vic2V0X3Jlc2lkdWFscyA8LSByZXNpZHVhbHMuZGZbcmVzaWR1YWxzLmRmJFNpdGUgPT0gc2l0ZSAmIHJlc2lkdWFscy5kZiR5ZWFyID09IHllYXIsIF0NCiAgDQogIGlmIChucm93KHN1YnNldF9yZXNpZHVhbHMpID09IDApIHsNCiAgICBtZXNzYWdlKHBhc3RlKCJObyBkYXRhIGZvciBTaXRlOiIsIHNpdGUsICJZZWFyOiIsIHllYXIsICItIHNraXBwaW5nLiIpKQ0KICAgIG5leHQNCiAgfQ0KICANCiAgIyBEZXRlcm1pbmUgdGhlIGRlcHRoIHRocmVzaG9sZCAoY3VzdG9tIG9yIFNEKQ0KICBkZXB0aF90aHJlc2hvbGQgPC0gaWYgKGlzLm51bGwoY3VzdG9tX2RlcHRoKSkgew0KICAgIHNkKHN1YnNldF9yZXNpZHVhbHMkcmVzaWR1YWxfZGVwdGgsIG5hLnJtID0gVFJVRSkNCiAgfSBlbHNlIHsNCiAgICBjdXN0b21fZGVwdGgNCiAgfQ0KICANCiAgIyBQcmludCB0aGUgZGVwdGggdGhyZXNob2xkDQogICNjYXQoIkRlcHRoIHRocmVzaG9sZCBmb3IgU2l0ZToiLCBzaXRlLCAiWWVhcjoiLCB5ZWFyLCAiaXM6IiwgZGVwdGhfdGhyZXNob2xkLCAiXG4iKQ0KICANCiAgICAjIEZpbHRlciBwb29scyBiYXNlZCBvbiBkZXB0aCB0aHJlc2hvbGQNCiAgICB2YWxpZF9wb29scyA8LSBzdWJzZXRfcmVzaWR1YWxzICU+JQ0KICAgICAgZ3JvdXBfYnkocG9vbF9pZCkgJT4lDQogICAgICBmaWx0ZXIobWF4KHJlc2lkdWFsX2RlcHRoLCBuYS5ybSA9IFRSVUUpID4gZGVwdGhfdGhyZXNob2xkKSAlPiUNCiAgICAgIHB1bGwocG9vbF9pZCkgJT4lDQogICAgICB1bmlxdWUoKQ0KICAgIA0KICAgICMgU3Vic2V0IHJlc2lkdWFscyBmb3IgdmFsaWQgcG9vbHMNCiAgICBzdWJzZXRfcmVzaWR1YWxzIDwtIHN1YnNldF9yZXNpZHVhbHNbc3Vic2V0X3Jlc2lkdWFscyRwb29sX2lkICVpbiUgdmFsaWRfcG9vbHMsIF0NCiAgICANCiAgICBpZiAobnJvdyhzdWJzZXRfcmVzaWR1YWxzKSA9PSAwKSB7DQogICAgICBtZXNzYWdlKHBhc3RlKCJObyB2YWxpZCBwb29scyBmb3IgU2l0ZToiLCBzaXRlLCAiWWVhcjoiLCB5ZWFyLCAiLSBza2lwcGluZy4iKSkNCiAgICAgIG5leHQNCiAgICB9DQogICAgDQogICAgIyBFbnN1cmUgdGhlIGRhdGFmcmFtZSBpcyBzb3J0ZWQgYnkgZGlzdGFuY2Ugd2l0aGluIGVhY2ggcG9vbA0KICAgIHN1YnNldF9yZXNpZHVhbHMgPC0gc3Vic2V0X3Jlc2lkdWFsc1tvcmRlcihzdWJzZXRfcmVzaWR1YWxzJHBvb2xfaWQsIHN1YnNldF9yZXNpZHVhbHMkZGlzdGFuY2UpLCBdDQogICAgDQojIEl0ZXJhdGUgb3ZlciBlYWNoIHVuaXF1ZSBwb29sX2lkDQp1bmlxdWVfcG9vbF9pZHMgPC0gdW5pcXVlKHN1YnNldF9yZXNpZHVhbHMkcG9vbF9pZCkNCmZvciAocG9vbF9pZCBpbiB1bmlxdWVfcG9vbF9pZHMpIHsNCiAgcG9vbF9yZXNpZHVhbHMgPC0gc3Vic2V0X3Jlc2lkdWFsc1tzdWJzZXRfcmVzaWR1YWxzJHBvb2xfaWQgPT0gcG9vbF9pZCwgXQ0KICANCiAgIyBJbml0aWFsaXplIHRoZSBzZWdtZW50X2xlbmd0aCBjb2x1bW4NCiAgcG9vbF9yZXNpZHVhbHMkc2VnbWVudF9sZW5ndGggPC0gTkENCiAgDQogICMgQ2FsY3VsYXRlIHNlZ21lbnQgbGVuZ3Rocw0KICBmb3IgKGkgaW4gMTpucm93KHBvb2xfcmVzaWR1YWxzKSkgew0KICAgIGlmIChpID09IDEpIHsNCiAgICAgICMgRmlyc3QgcG9pbnQ6IG9ubHkgaGFsZiB0aGUgZGlzdGFuY2UgdG8gdGhlIG5leHQgcG9pbnQNCiAgICAgIHBvb2xfcmVzaWR1YWxzJHNlZ21lbnRfbGVuZ3RoW2ldIDwtIChwb29sX3Jlc2lkdWFscyRkaXN0YW5jZVtpICsgMV0gLSBwb29sX3Jlc2lkdWFscyRkaXN0YW5jZVtpXSkgLyAyDQogICAgfSBlbHNlIGlmIChpID09IG5yb3cocG9vbF9yZXNpZHVhbHMpKSB7DQogICAgICAjIExhc3QgcG9pbnQ6IG9ubHkgaGFsZiB0aGUgZGlzdGFuY2UgdG8gdGhlIHByZXZpb3VzIHBvaW50DQogICAgICBwb29sX3Jlc2lkdWFscyRzZWdtZW50X2xlbmd0aFtpXSA8LSAocG9vbF9yZXNpZHVhbHMkZGlzdGFuY2VbaV0gLSBwb29sX3Jlc2lkdWFscyRkaXN0YW5jZVtpIC0gMV0pIC8gMg0KICAgIH0gZWxzZSB7DQogICAgICAjIE1pZGRsZSBwb2ludHM6IGhhbGYgdGhlIGRpc3RhbmNlIHRvIHRoZSBwcmV2aW91cyBhbmQgbmV4dCBwb2ludHMNCiAgICAgIHBvb2xfcmVzaWR1YWxzJHNlZ21lbnRfbGVuZ3RoW2ldIDwtIA0KICAgICAgICAoKHBvb2xfcmVzaWR1YWxzJGRpc3RhbmNlW2ldIC0gcG9vbF9yZXNpZHVhbHMkZGlzdGFuY2VbaSAtIDFdKSAvIDIpICsNCiAgICAgICAgKChwb29sX3Jlc2lkdWFscyRkaXN0YW5jZVtpICsgMV0gLSBwb29sX3Jlc2lkdWFscyRkaXN0YW5jZVtpXSkgLyAyKQ0KICAgIH0NCiAgfQ0KICANCiAgIyBQb29sIG1ldHJpY3MNCiAgcG9vbF9sZW5ndGggPC0gc3VtKHBvb2xfcmVzaWR1YWxzJHNlZ21lbnRfbGVuZ3RoLCBuYS5ybSA9IFRSVUUpDQogIHZlZ19sZW5ndGggPC0gc3VtKHBvb2xfcmVzaWR1YWxzJHNlZ21lbnRfbGVuZ3RoW3Bvb2xfcmVzaWR1YWxzW1t2ZWdfY29sdW1uXV0gPiAwXSwgbmEucm0gPSBUUlVFKQ0KICB2ZWdfcHJvcG9ydGlvbmFsX2xlbmd0aCA8LSB2ZWdfbGVuZ3RoIC8gcG9vbF9sZW5ndGgNCiAgdmVnX3Byb3BvcnRpb25hbF9hcmVhIDwtIHN1bShwb29sX3Jlc2lkdWFsc1tbdmVnX2NvbHVtbl1dICogcG9vbF9yZXNpZHVhbHMkc2VnbWVudF9sZW5ndGgsIG5hLnJtID0gVFJVRSkgLyBwb29sX2xlbmd0aCAjd2UgZG8gbm90IHVzZSByZXNpZHVhbCB3aWR0aHMgaGVyZSwgd2hpY2ggY291bGQgY29tcGxpY2F0ZSBpbnRlcnByZXRhdGlvbiAoZS5nLiwgYXJlYXMgb2Ygd2V0dGVkIHZlZ2V0YXRpb24gZ3JlYXRlciB0aGFuIHRoZSB3ZXR0ZWQgYXJlYSkgd2l0aG91dCBhbnkgYmVuZWZpdCB0aGF0IHdlIGFyZSBhd2FyZSBvZi4NCg0KICAjIFN0b3JlIHJlc3VsdHMNCiAgdmVnX3Byb3BvcnRpb25fbGlzdFtbcGFzdGUoc2l0ZSwgeWVhciwgcG9vbF9pZCwgc2VwID0gIl8iKV1dIDwtIGxpc3QoDQogICAgc2l0ZSA9IHNpdGUsDQogICAgeWVhciA9IHllYXIsDQogICAgcG9vbF9pZCA9IHBvb2xfaWQsDQogICAgcG9vbF9sZW5ndGggPSBwb29sX2xlbmd0aCwNCiAgICB2ZWdfbGVuZ3RoID0gdmVnX2xlbmd0aCwNCiAgICB2ZWdfcHJvcG9ydGlvbmFsX2xlbmd0aCA9IHZlZ19wcm9wb3J0aW9uYWxfbGVuZ3RoLA0KICAgIHZlZ19wcm9wb3J0aW9uYWxfYXJlYSA9IHZlZ19wcm9wb3J0aW9uYWxfYXJlYQ0KICApDQp9DQoNCiAgICAjIFNpdGUtWWVhciBUb3RhbHMNCiAgICB0b3RhbF9wb29sX2xlbmd0aCA8LSBzdW0oc2FwcGx5KHZlZ19wcm9wb3J0aW9uX2xpc3QsIGZ1bmN0aW9uKHgpIGlmICh4JHNpdGUgPT0gc2l0ZSAmJiB4JHllYXIgPT0geWVhcikgeCRwb29sX2xlbmd0aCBlbHNlIDApLCBuYS5ybSA9IFRSVUUpDQogICAgdG90YWxfdmVnX2xlbmd0aCA8LSBzdW0oc2FwcGx5KHZlZ19wcm9wb3J0aW9uX2xpc3QsIGZ1bmN0aW9uKHgpIGlmICh4JHNpdGUgPT0gc2l0ZSAmJiB4JHllYXIgPT0geWVhcikgeCR2ZWdfbGVuZ3RoIGVsc2UgMCksIG5hLnJtID0gVFJVRSkNCiAgICB0b3RhbF92ZWdfcHJvcG9ydGlvbmFsX2xlbmd0aCA8LSB0b3RhbF92ZWdfbGVuZ3RoIC8gdG90YWxfcG9vbF9sZW5ndGgNCiAgICB0b3RhbF92ZWdfcHJvcG9ydGlvbmFsX2FyZWEgPC0gc3VtKHNhcHBseSh2ZWdfcHJvcG9ydGlvbl9saXN0LCBmdW5jdGlvbih4KSBpZiAoeCRzaXRlID09IHNpdGUgJiYgeCR5ZWFyID09IHllYXIpIHgkdmVnX3Byb3BvcnRpb25hbF9hcmVhICogeCRwb29sX2xlbmd0aCBlbHNlIDApLCBuYS5ybSA9IFRSVUUpIC8gdG90YWxfcG9vbF9sZW5ndGgNCiAgICANCiAgICB2ZWdfcHJvcG9ydGlvbl9saXN0W1twYXN0ZShzaXRlLCB5ZWFyLCAiVG90YWwiLCBzZXAgPSAiXyIpXV0gPC0gbGlzdCgNCiAgICAgIHNpdGUgPSBzaXRlLA0KICAgICAgeWVhciA9IHllYXIsDQogICAgICBwb29sX2lkID0gIlRvdGFsIiwNCiAgICAgIHBvb2xfbGVuZ3RoID0gdG90YWxfcG9vbF9sZW5ndGgsDQogICAgICB2ZWdfbGVuZ3RoID0gdG90YWxfdmVnX2xlbmd0aCwNCiAgICAgIHZlZ19wcm9wb3J0aW9uYWxfbGVuZ3RoID0gdG90YWxfdmVnX3Byb3BvcnRpb25hbF9sZW5ndGgsDQogICAgICB2ZWdfcHJvcG9ydGlvbmFsX2FyZWEgPSB0b3RhbF92ZWdfcHJvcG9ydGlvbmFsX2FyZWENCiAgICApDQogIH0NCiAgDQogICMgQ29tYmluZSBpbnRvIGEgZGF0YWZyYW1lDQogIHZlZ19wcm9wb3J0aW9uX2RmIDwtIGRvLmNhbGwocmJpbmQsIGxhcHBseSh2ZWdfcHJvcG9ydGlvbl9saXN0LCBmdW5jdGlvbih4KSB7DQogICAgZGF0YS5mcmFtZSgNCiAgICAgIHNpdGUgPSB4JHNpdGUsDQogICAgICB5ZWFyID0geCR5ZWFyLA0KICAgICAgcG9vbF9pZCA9IHgkcG9vbF9pZCwNCiAgICAgIHBvb2xfbGVuZ3RoID0geCRwb29sX2xlbmd0aCwNCiAgICAgIHZlZ19sZW5ndGggPSB4JHZlZ19sZW5ndGgsDQogICAgICB2ZWdfcHJvcG9ydGlvbmFsX2xlbmd0aCA9IHgkdmVnX3Byb3BvcnRpb25hbF9sZW5ndGgsDQogICAgICB2ZWdfcHJvcG9ydGlvbmFsX2FyZWEgPSB4JHZlZ19wcm9wb3J0aW9uYWxfYXJlYQ0KICAgICkNCiAgfSkpDQogIA0KICByZXR1cm4odmVnX3Byb3BvcnRpb25fZGYpDQp9DQpgYGANClRoZSB0YWJsZXMgZ2VuZXJhdGVkIGFuZCBleHBvcnRlZCBieSB0aGUgY29kZSBiZWxvdyB3aWxsIHNob3cgdGhlIHByb3BvcnRpb25hbCBsZW5ndGggb2YgcmVzaWR1YWwgcG9vbHMgaW4gd2hpY2ggYXF1YXRpYyB2ZWdldGF0aW9uIHdhcyBwcmVzZW50IChyZWdhcmRsZXNzIG9mIHF1YW50aXR5L3dpZHRoKSwgaW4gdGhlIHNhbWUgd2F5IHRoYXQgd2UgdXNlZCB0aGUgZmluZXMgZGF0YS4gVGhlIHRhYmxlcyBhbHNvIHNob3cgdGhlIHBsYW4gYXJlYSBvZiByZXNpZHVhbCBwb29scyB0aGF0IGZlYXR1cmVkIGFxdWF0aWMgdmVnZXRhdGlvbiwgYmFzZWQgb24geW91ciBlc3RpbWF0ZXMgb2YgdGhlIHByb3BvcnRpb24gb2Ygd2V0dGVkIHdpZHRoIG9jY3VwaWVkIGJ5IHZlZ2V0YXRpb24gYXQgZWFjaCBpbnRlcnZhbCwgaW50ZWdyYXRlZCBhbG9uZyB0aGUgbGVuZ3RoIG9mIGVhY2ggcG9vbC4NCg0KSnVzdCBsaWtlIGZvciBmaW5lcywgZm9yIGFxdWF0aWMgdmVnZXRhdGlvbiB3ZSBkZWZhdWx0IHRvIHVzaW5nIHRoZSBmdWxsIGNvbnRpbmdlbnQgb2YgcG9vbHMuIE91ciByYXRpb25hbGUgaXMgdGhhdCB2ZWdldGF0aW9uIChwYXJ0aWN1bGFybHkgY2VydGFpbiBwcm9ibGVtYXRpYyBpbnZhc2l2ZSBzcGVjaWVzKSBjYW4gYmUgaW52b2x2ZWQgaW4gdGhlIHByb2Nlc3Mgb2YgaW5maWxsaW5nIHBvb2xzIGJ5IHRyYXBwaW5nIHNlZGltZW50LCBhbmQgaXQgbWF5IGJlIG9mIHJlc3RvcmF0aW9uIHNpZ25pZmljYW5jZSB0byB0cmFjayBjaGFuZ2VzIGluIHZlZ2V0YXRpb24gaW4gbWlub3IgbmFzY2VudCBvciBpbmZpbGxpbmcgcG9vbHMuIEhvd2V2ZXIsIGFzIGJlZm9yZSwgd2UgaGF2ZSBpbmNsdWRlZCBpbiB0aGUgY29kZSBiZWxvdyB0aGUgYWJpbGl0eSB0byBzZWxlY3QgYSBzdWJzZXQgb2YgcG9vbHMsIGZvciBleGFtcGxlIGlmIHlvdSB3YW50IHRvIGZvY3VzIG9uIGZhY3RvcnMgc3VjaCBhcyB0aGUgaW1wb3J0YW5jZSBvZiBhcXVhdGljIHZlZ2V0YXRpdmUgY292ZXIgdGhhdCB3b3VsZCBwbGF1c2libHkgYmUgdXNlZCBieSByZWFyaW5nIGZpc2ggaW4gc3VtbWVyIChpLmUuLCBvbmx5IGluIHBvb2xzIG9mIGEgY2VydGFpbiBkZXB0aCkuIE91ciBkZWZhdWx0IGlzIDAgKG5vIHN1YnNldHRpbmcpLCBhbmQgaWYgeW91IGNoYW5nZSBpdCwgZW5zdXJlIHRoYXQgd2hlbiBjb21wYXJpbmcgc3lzdGVtcyBvciB5ZWFycyB5b3UgYXJlIGNvbXBhcmluZyBsaWtlIGZvciBsaWtlLg0KDQpgYGB7ciBBcXVhdGljIHZlZyBjdXN0b20gdGhyZXNob2xkfQ0KIyBEZWZpbmUgY3VzdG9tIHRocmVzaG9sZCBpZiByZXF1aXJlZC4gV2UgcmVjb21tZW5kIDAgKGFsbCByZXNpZHVhbCBwb29scywgcmVnYXJkbGVzcyBvZiBtYXhpbXVtIGRlcHRoKQ0KY3VzdG9tX2RlcHRoIDwtIDAgICMgUmVwbGFjZSB3aXRoIHlvdXIgZGVzaXJlZCB0aHJlc2hvbGQgaW4gbWV0cmVzLCBvciBzZXQgdG8gTlVMTCB0byB1c2UgdGhlIHN0YW5kYXJkIGRldmlhdGlvbiBvZiB0aGUgcmVhY2ggKHRoYXQgeWVhcikNCmBgYA0KDQpgYGB7ciBBcXVhdGljIHZlZyB0YWJsZXMsIGVjaG8gPSBGQUxTRSwgbWVzc2FnZT1GQUxTRX0NCiMgQ2FsbCB0aGUgZnVuY3Rpb24gd2l0aCB0aGUgY3VzdG9tIGRlcHRoIHRocmVzaG9sZA0Kc3VidmVnX3Jlc3VsdCA8LSBjYWxjdWxhdGVfdmVnX3Byb3BvcnRpb24ocmVzaWR1YWxzLmRmLCB2ZWdfY29sdW1uID0gInN1YnZlZyIsIGN1c3RvbV9kZXB0aCA9IGN1c3RvbV9kZXB0aCkNCmVtZXJndmVnX3Jlc3VsdCA8LSBjYWxjdWxhdGVfdmVnX3Byb3BvcnRpb24ocmVzaWR1YWxzLmRmLCB2ZWdfY29sdW1uID0gImVtZXJndmVnIiwgY3VzdG9tX2RlcHRoID0gY3VzdG9tX2RlcHRoKQ0KZmxvYXR2ZWdfcmVzdWx0IDwtIGNhbGN1bGF0ZV92ZWdfcHJvcG9ydGlvbihyZXNpZHVhbHMuZGYsIHZlZ19jb2x1bW4gPSAiZmxvYXR2ZWciLCBjdXN0b21fZGVwdGggPSBjdXN0b21fZGVwdGgpDQoNCiMgRXh0cmFjdCAiVG90YWwiIHJvd3MgZm9yIGVhY2ggdGFibGUNCnN1YnZlZ190b3RhbCA8LSBzdWJ2ZWdfcmVzdWx0W3N1YnZlZ19yZXN1bHQkcG9vbF9pZCA9PSAiVG90YWwiLCBdDQplbWVyZ3ZlZ190b3RhbCA8LSBlbWVyZ3ZlZ19yZXN1bHRbZW1lcmd2ZWdfcmVzdWx0JHBvb2xfaWQgPT0gIlRvdGFsIiwgXQ0KZmxvYXR2ZWdfdG90YWwgPC0gZmxvYXR2ZWdfcmVzdWx0W2Zsb2F0dmVnX3Jlc3VsdCRwb29sX2lkID09ICJUb3RhbCIsIF0NCg0KIyBFeHBvcnQgdGhlICJUb3RhbCIgcm93cyBmb3IgZWFjaCB2ZWdldGF0aW9uIHR5cGUgYXMgQ1NWIGZpbGVzDQpleHBvcnRfdGFibGUoc3VidmVnX3RvdGFsLCAiUmVhY2h3aWRlIFN1Ym1lcmdlZCBWZWcuY3N2IikgI2NhbiBhbHRlciB0aGVzZSB0byBzdWJ2ZWdfcmVzdWx0IChldGMuKSBpZiBmdWxsIGRhdGEgcmVxdWlyZWQNCmV4cG9ydF90YWJsZShlbWVyZ3ZlZ190b3RhbCwgIlJlYWNod2lkZSBFbWVyZ2VudCBWZWcuY3N2IikNCmV4cG9ydF90YWJsZShmbG9hdHZlZ190b3RhbCwgIlJlYWNod2lkZSBGbG9hdGluZyBWZWcuY3N2IikNCg0KIyBQcmludCB0YWJsZXMgZm9yIHZpc3VhbGl6YXRpb24gaW4gUlN0dWRpbyAvIGtuaXQNCmthYmxlKHN1YnZlZ190b3RhbCwgY2FwdGlvbiA9ICJSZWFjaHdpZGUgU3VibWVyZ2VkIFZlZ2V0YXRpb24gZm9yIEVhY2ggU2l0ZS1ZZWFyIikNCmthYmxlKGVtZXJndmVnX3RvdGFsLCBjYXB0aW9uID0gIlJlYWNod2lkZSBFbWVyZ2VudCBWZWdldGF0aW9uIGZvciBFYWNoIFNpdGUtWWVhciIpDQprYWJsZShmbG9hdHZlZ190b3RhbCwgY2FwdGlvbiA9ICJSZWFjaHdpZGUgRmxvYXRpbmcgVmVnZXRhdGlvbiBmb3IgRWFjaCBTaXRlLVllYXIiKQ0KYGBgDQoNCiMjIEluZmVyZW50aWFsIFRlc3RzIC0gQXF1YXRpYyBWZWcNCg0KSnVzdCBsaWtlIHdpdGggdGhlIGZpbmVzIGRhdGEsIHdlIGFyZSBkZWFsaW5nIHdpdGggZGF0YSB0aGF0IGFyZSBib3VuZGVkIGJ5IDAgYW5kIDEgKGZvciBib3RoIHByb3BvcnRpb25zIG9mIGxlbmd0aCBhbmQgZm9yIGFyZWEsIGFjcm9zcyBlYWNoIHR5cGUgb2YgdmVnZXRhdGlvbikuIFRoZSBub24tdHJhbnNmb3JtZWQgZGF0YSB3b3VsZCBiZSBleHBlY3RlZCB0byB2aW9sYXRlIHRoZSBhc3N1bXB0aW9ucyBvZiBBTk9WQSwgc28gd2Ugb21pdCB0aGUgaW5pdGlhbCBkaWFnbm9zdGljIHRlc3RzLiBXZSB3aWxsIGFnYWluIGFwcGx5IEJldGEgcmVncmVzc2lvbnMuDQoNCkJlbG93IHdlIGRpc3BsYXkgdGhlIEJldGEgcmVncmVzc2lvbiBtb2RlbCBzdW1tYXJpZXMgZm9yIGFsbCB2ZWdldGF0aW9uIGNhdGVnb3JpZXMgKHdoZXJlIHByZXNlbnQpLCBib3RoIGxlbmd0aCBhbmQgYXJlYSBwcm9wb3J0aW9ucy4gV2Ugb21pdCB0aGUgZGlhZ25vc3RpYyBwbG90cyBmcm9tIHRoZSBkaXNwbGF5LCBidXQgd2hlbiB5b3UgcnVuIHRoZSBjb2RlIGZvciB5b3VyIGRhdGEsIHlvdSBzaG91bGQgZXhhbWluZSB0aGUgcGxvdHMuDQoNCmBgYHtyIGFxdWF0aWMgdmVnIGluZmVyZW50aWFscywgZWNobyA9IEZBTFNFfQ0KIyBGdW5jdGlvbiB0byBydW4gQmV0YSByZWdyZXNzaW9uIGFuZCBkaWFnbm9zdGljcw0KcnVuX2JldGFfcmVncmVzc2lvbiA8LSBmdW5jdGlvbihkYXRhLCByZXNwb25zZV92YXIsIGRhdGFzZXRfbmFtZSwgc3VtbWFyeV9saXN0KSB7DQogICMgQ3JlYXRlIHRoZSBUaW1lX0NhdGVnb3J5DQogIGRhdGEgPC0gZGF0YSAlPiUNCiAgICBtdXRhdGUoVGltZV9DYXRlZ29yeSA9IGNhc2Vfd2hlbigNCiAgICAgIHllYXIgJWluJSBiZWZvcmVfeWVhcnMgfiAiQmVmb3JlIiwNCiAgICAgIHllYXIgJWluJSBhZnRlcl95ZWFycyB+ICJBZnRlciIsDQogICAgICBUUlVFIH4gTkFfY2hhcmFjdGVyXw0KICAgICkpDQoNCiAgIyBGaWx0ZXIgc2l0ZXMgd2l0aCBib3RoIHRpbWUgY2F0ZWdvcmllcyBhbmQgcmVtb3ZlICJUb3RhbCINCiAgZmlsdGVyZWRfZGF0YSA8LSBkYXRhICU+JQ0KICAgIGZpbHRlcihwb29sX2lkICE9ICJUb3RhbCIpICU+JQ0KICAgIGdyb3VwX2J5KHNpdGUpICU+JQ0KICAgIGZpbHRlcihhbGwoYygiQmVmb3JlIiwgIkFmdGVyIikgJWluJSBUaW1lX0NhdGVnb3J5KSkgJT4lDQogICAgdW5ncm91cCgpDQoNCiAgIyBBZGp1c3QgcmVzcG9uc2UgdmFyaWFibGUgdmFsdWVzIG9mIGV4YWN0bHkgMCBvciAxDQogIGZpbHRlcmVkX2RhdGEgPC0gZmlsdGVyZWRfZGF0YSAlPiUNCiAgICBtdXRhdGUocmVzcG9uc2VfYWRqdXN0ZWQgPSBjYXNlX3doZW4oDQogICAgICAhIXN5bShyZXNwb25zZV92YXIpID09IDAgfiAwLjAwMSwNCiAgICAgICEhc3ltKHJlc3BvbnNlX3ZhcikgPT0gMSB+IDAuOTk5LA0KICAgICAgVFJVRSB+ICEhc3ltKHJlc3BvbnNlX3ZhcikNCiAgICApKQ0KDQogICMgRml0IEJldGEgcmVncmVzc2lvbiBtb2RlbA0KICBiZXRhX21vZGVsIDwtIHRyeUNhdGNoKA0KICAgIGJldGFyZWcocmVzcG9uc2VfYWRqdXN0ZWQgfiBzaXRlICogVGltZV9DYXRlZ29yeSwgZGF0YSA9IGZpbHRlcmVkX2RhdGEpLA0KICAgIHdhcm5pbmcgPSBmdW5jdGlvbih3KSB7DQogICAgICB3YXJuaW5nX21lc3NhZ2UgPC0gcGFzdGUoIlxuV2FybmluZzogb3B0aW1pemF0aW9uIGZhaWxlZCB0byBjb252ZXJnZSBmb3IiLCByZXNwb25zZV92YXIsICJpbiIsIGRhdGFzZXRfbmFtZSwgImRhdGFzZXRcbiIpDQogICAgICBjYXQod2FybmluZ19tZXNzYWdlKSAgIyBEaXNwbGF5IHRoZSB3YXJuaW5nIG1lc3NhZ2UNCiAgICAgIHJldHVybihOVUxMKQ0KICAgIH0NCiAgKQ0KDQogIGlmICghaXMubnVsbChiZXRhX21vZGVsKSkgew0KICAgICMgSWYgbW9kZWwgY29udmVyZ2VzLCBjYXB0dXJlIHRoZSBzdW1tYXJ5IGFuZCBkaXNwbGF5IGl0DQogICAgbW9kZWxfc3VtbWFyeSA8LSBjYXB0dXJlLm91dHB1dChzdW1tYXJ5KGJldGFfbW9kZWwpKQ0KICAgIA0KICAgICMgQXBwZW5kIHRoZSBzdW1tYXJ5IHRvIHRoZSBsaXN0DQogICAgc3VtbWFyeV9saXN0IDwtIGMoc3VtbWFyeV9saXN0LCBwYXN0ZSgiU3RhcnQgb2Ygc3VtbWFyeSBmb3IiLCByZXNwb25zZV92YXIsICJpbiIsIGRhdGFzZXRfbmFtZSwgImRhdGFzZXQiKSwgbW9kZWxfc3VtbWFyeSwgcGFzdGUoIlxuXG5cbiIpKQ0KICAgIA0KICAgICMgUHJpbnQgdGhlIG1vZGVsIHN1bW1hcnkgdG8gdGhlIGNvbnNvbGUNCiAgICBjYXQoIlxuXG5cbk1vZGVsIFN1bW1hcnkgZm9yIiwgcmVzcG9uc2VfdmFyLCAiaW4iLCBkYXRhc2V0X25hbWUsICJkYXRhc2V0OlxuIikNCiAgICBwcmludChzdW1tYXJ5KGJldGFfbW9kZWwpKQ0KICB9IGVsc2Ugew0KICAgICMgSWYgbW9kZWwgZG9lcyBub3QgY29udmVyZ2UsIGp1c3QgcHJpbnQgYSBtZXNzYWdlDQogICAgY2F0KCJcblxuXG5ObyBtb2RlbCBjb252ZXJnZW5jZSBmb3IiLCByZXNwb25zZV92YXIsICJpbiIsIGRhdGFzZXRfbmFtZSwgIlxuIikNCiAgfQ0KDQogIHJldHVybihzdW1tYXJ5X2xpc3QpDQp9DQoNCiMgRGVmaW5lIGRhdGFzZXRzIGFuZCByZXNwb25zZSB2YXJpYWJsZXMNCmRhdGFzZXRzIDwtIGxpc3Qoc3VidmVnX3Jlc3VsdCA9IHN1YnZlZ19yZXN1bHQsIA0KICAgICAgICAgICAgICAgICBlbWVyZ3ZlZ19yZXN1bHQgPSBlbWVyZ3ZlZ19yZXN1bHQsIA0KICAgICAgICAgICAgICAgICBmbG9hdHZlZ19yZXN1bHQgPSBmbG9hdHZlZ19yZXN1bHQpDQpyZXNwb25zZV92YXJzIDwtIGMoInZlZ19wcm9wb3J0aW9uYWxfbGVuZ3RoIiwgInZlZ19wcm9wb3J0aW9uYWxfYXJlYSIpDQoNCiMgSW5pdGlhbGl6ZSBhbiBlbXB0eSBsaXN0IHRvIHN0b3JlIGFsbCBzdW1tYXJpZXMNCmFsbF9zdW1tYXJpZXMgPC0gY2hhcmFjdGVyKCkNCg0KIyBSdW4gdGhlIGZ1bmN0aW9uIGZvciBlYWNoIGNvbWJpbmF0aW9uIG9mIGRhdGFzZXQgYW5kIHJlc3BvbnNlIHZhcmlhYmxlDQpmb3IgKGRhdGFzZXRfbmFtZSBpbiBuYW1lcyhkYXRhc2V0cykpIHsNCiAgZm9yIChyZXNwb25zZV92YXIgaW4gcmVzcG9uc2VfdmFycykgew0KICAgIGFsbF9zdW1tYXJpZXMgPC0gcnVuX2JldGFfcmVncmVzc2lvbihkYXRhc2V0c1tbZGF0YXNldF9uYW1lXV0sIHJlc3BvbnNlX3ZhciwgZGF0YXNldF9uYW1lLCBhbGxfc3VtbWFyaWVzKQ0KICB9DQp9DQoNCiMgRXhwb3J0IGFsbCBzdW1tYXJpZXMgYXMgYSBzaW5nbGUgLnR4dCBmaWxlLiBTdW1tYXJpZXMgZ2VuZXJhdGVkIHdpdGhpbiBmdW5jdGlvbg0KZXhwb3J0X3N1bW1hcnkoYWxsX3N1bW1hcmllcywgIkFxdWF0aWMgVmVnZXRhdGlvbiBCZXRhIFJlZ3Jlc3Npb25zIikNCmBgYA0KDQpgYGB7ciBhcXVhdGljIHZlZyBkaWFnbm9zdGljIHBsb3RzLCBpbmNsdWRlPUZBTFNFfQ0KZm9yIChkYXRhc2V0X25hbWUgaW4gbmFtZXMoZGF0YXNldHMpKSB7DQogIGZvciAocmVzcG9uc2VfdmFyIGluIHJlc3BvbnNlX3ZhcnMpIHsNCiAgICAjIERhdGEgcHJlcHJvY2Vzc2luZyBmb3IgcGxvdHRpbmcNCiAgICBkYXRhIDwtIGRhdGFzZXRzW1tkYXRhc2V0X25hbWVdXSAlPiUNCiAgICAgIG11dGF0ZShUaW1lX0NhdGVnb3J5ID0gY2FzZV93aGVuKA0KICAgICAgICB5ZWFyICVpbiUgYmVmb3JlX3llYXJzIH4gIkJlZm9yZSIsDQogICAgICAgIHllYXIgJWluJSBhZnRlcl95ZWFycyB+ICJBZnRlciIsDQogICAgICAgIFRSVUUgfiBOQV9jaGFyYWN0ZXJfDQogICAgICApKSAlPiUNCiAgICAgIGZpbHRlcihwb29sX2lkICE9ICJUb3RhbCIpICU+JQ0KICAgICAgbXV0YXRlKHJlc3BvbnNlX2FkanVzdGVkID0gY2FzZV93aGVuKA0KICAgICAgICAhIXN5bShyZXNwb25zZV92YXIpID09IDAgfiAwLjAwMSwNCiAgICAgICAgISFzeW0ocmVzcG9uc2VfdmFyKSA9PSAxIH4gMC45OTksDQogICAgICAgIFRSVUUgfiAhIXN5bShyZXNwb25zZV92YXIpDQogICAgICApKQ0KDQogICAgIyBEaXN0cmlidXRpb24gb2YgdGhlIHJlc3BvbnNlIHZhcmlhYmxlDQogICAgcHJpbnQoZ2dwbG90KGRhdGEsIGFlcyh4ID0gcmVzcG9uc2VfYWRqdXN0ZWQpKSArDQogICAgICBnZW9tX2hpc3RvZ3JhbShiaW5zID0gMzAsIGZpbGwgPSAiYmx1ZSIsIGFscGhhID0gMC43KSArDQogICAgICBnZW9tX2RlbnNpdHkoY29sb3IgPSAicmVkIiwgbGluZXdpZHRoID0gMSkgKw0KICAgICAgbGFicyh0aXRsZSA9IHBhc3RlKCJEaXN0cmlidXRpb24gb2YiLCByZXNwb25zZV92YXIsICIoQWRqdXN0ZWQpIiwgImZvciIsIGRhdGFzZXRfbmFtZSksDQogICAgICAgICAgIHggPSBwYXN0ZShyZXNwb25zZV92YXIsICIoQWRqdXN0ZWQpIiksIHkgPSAiRnJlcXVlbmN5IikgKw0KICAgICAgdGhlbWVfbWluaW1hbCgpKQ0KDQojIEFkZCByZXNpZHVhbHMgYW5kIGZpdHRlZCB2YWx1ZXMgZm9yIGRpYWdub3N0aWNzDQppZiAoIWlzLm51bGwoYmV0YV9tb2RlbCkpIHsNCiAgIyBFeHRyYWN0IHRoZSBkYXRhIHVzZWQgaW4gdGhlIG1vZGVsDQogIG1vZGVsX2RhdGEgPC0gbW9kZWwuZnJhbWUoYmV0YV9tb2RlbCkNCiAgDQogICMgQWRkIHJlc2lkdWFscyBhbmQgZml0dGVkIHZhbHVlcyB0byB0aGUgbW9kZWwgZGF0YQ0KICBtb2RlbF9kYXRhIDwtIG1vZGVsX2RhdGEgJT4lDQogICAgbXV0YXRlKHJlc2lkdWFscyA9IHJlc2lkdWFscyhiZXRhX21vZGVsLCB0eXBlID0gInBlYXJzb24iKSwNCiAgICAgICAgICAgZml0dGVkID0gZml0dGVkKGJldGFfbW9kZWwpKQ0KICANCiAgIyBQZXJmb3JtIGRpYWdub3N0aWNzDQogICMgUmVzaWR1YWxzIGRpc3RyaWJ1dGlvbg0KICBwcmludChnZ3Bsb3QobW9kZWxfZGF0YSwgYWVzKHggPSByZXNpZHVhbHMpKSArDQogICAgZ2VvbV9oaXN0b2dyYW0oYmlucyA9IDMwLCBmaWxsID0gImJsdWUiLCBhbHBoYSA9IDAuNykgKw0KICAgIGdlb21fZGVuc2l0eShjb2xvciA9ICJyZWQiLCBzaXplID0gMSkgKw0KICAgIGxhYnModGl0bGUgPSBwYXN0ZSgiUmVzaWR1YWxzIERpc3RyaWJ1dGlvbiBmb3IiLCByZXNwb25zZV92YXIsICJpbiIsIGRhdGFzZXRfbmFtZSksDQogICAgICAgICB4ID0gIlJlc2lkdWFscyIsIHkgPSAiRnJlcXVlbmN5IikgKw0KICAgIHRoZW1lX21pbmltYWwoKSkNCiAgDQogICMgRml0dGVkIHZzIHJlc2lkdWFscw0KICBwcmludChnZ3Bsb3QobW9kZWxfZGF0YSwgYWVzKHggPSBmaXR0ZWQsIHkgPSByZXNpZHVhbHMpKSArDQogICAgZ2VvbV9wb2ludChhbHBoYSA9IDAuNSkgKw0KICAgIGdlb21faGxpbmUoeWludGVyY2VwdCA9IDAsIGxpbmV0eXBlID0gImRhc2hlZCIsIGNvbG9yID0gInJlZCIpICsNCiAgICBsYWJzKHRpdGxlID0gcGFzdGUoIkZpdHRlZCB2cyBSZXNpZHVhbHMgZm9yIiwgcmVzcG9uc2VfdmFyLCAiaW4iLCBkYXRhc2V0X25hbWUpLA0KICAgICAgICAgeCA9ICJGaXR0ZWQgVmFsdWVzIiwgeSA9ICJSZXNpZHVhbHMiKSArDQogICAgdGhlbWVfbWluaW1hbCgpKQ0KfQ0KDQogIH0NCn0NCmBgYA0KDQpIZXJlIGlzIHRoYXQgYmFzaWMgaW50ZXJwcmV0YXRpb24gYXNzaXN0YW5jZSBmcm9tIGJlZm9yZSwgYnV0IGFsc28gcmVtZW1iZXIgdGhhdCB0aGVyZSBpcyBleHRyYSBudWFuY2Ugbm93IHlvdSBhcmUgZGVhbGluZyB3aXRoIHByb3BvcnRpb25zIG9mIHBvb2wgbGVuZ3RoIG9yIHByb3BvcnRpb24gb2YgcG9vbCBwbGFuIGFyZWEuDQoNCi0gIk9wdGltaXphdGlvbiBmYWlsZWQgdG8gY29udmVyZ2UuLi4iIElmIHlvdSBzZWUgdGhpcyB3YXJuaW5nLCBpdCBtYXkgYmUgdGhhdCB0aGVyZSB3ZXJlIDAgdmFsdWVzIGFjcm9zcyBhbiBlbnRpcmUgU2l0ZS4gVGhpcyBzaG91bGQgYmUgZmFpcmx5IGVhc3kgdG8gaW50ZXJwcmV0IHdpdGhvdXQgaW5mZXJlbnRpYWwgdGVzdHMuDQoNCi0gUXVhbnRpbGUgcmVzaWR1YWxzIG1lYXN1cmUgdGhlIGRpZmZlcmVuY2UgYmV0d2VlbiB0aGUgYWN0dWFsIGRhdGEgYW5kIHByZWRpY3RlZCB2YWx1ZXMuIFRoZSBtZWRpYW4gc2hvdWxkIGJlIGNsb3NlIHRvIDAuIEFsc28gY2hlY2sgdGhlIHJlc2lkdWFscyB2cyBmaXR0ZWQgcGxvdCB0byBlbnN1cmUgdGhlcmUgaXMgbm8gY2xlYXIgdHJlbmQgb3IgdW51c3VhbCBvdXRsaWVycw0KDQotIENvZWZmaWNpZW50cyAobWVhbiBtb2RlbCk6IHRoZXNlIGFyZSB0aGUgZWZmZWN0cyBvZiB0aGUgcHJlZGljdG9ycyAoc2l0ZSwgdGltZSkgb24gdGhlIHJlc3BvbnNlIHZhcmlhYmxlIChmaW5lIHNlZGltZW50IHByb3BvcnRpb24gaW4gcG9vbHMpLiAqKkxvb2sgZm9yIHNpZ25pZmljYW50IHAgdmFsdWVzIGluIHRoZSBsYXN0IGNvbHVtbiwgcGFydGljdWxhcmx5IGZvciB0aGUgU2l0ZVxfXF9cX1xfXF9cOlRpbWVcX0NhdGVnb3J5XF9cX1xfXF9cXyByb3csIHdoaWNoIGlzIHRoZSBpbnRlcmFjdGlvbiB0ZXJtIChpZiBzaWduaWZpY2FudCwgdGhpcyBtZWFucyB0aGUgcHJvcG9ydGlvbiBvZiBmaW5lcyBpbiByZXNpZHVhbCBwb29scyBjaGFuZ2VkIG92ZXIgdGltZSBkaWZmZXJlbnRseSBiZXR3ZWVuIHNpdGVzKSoqLiANCg0KLSBQaGkgY29lZmZpY2llbnRzOiB0aGVyZSBpcyBhIHAtdmFsdWUgaGVyZSBhcyB3ZWxsLCBidXQgdGhpcyByZWZlcnMgdG8gd2hldGhlciB0aGUgc3ByZWFkIG9mIHRoZSBkYXRhIGFyb3VuZCB0aGUgbWVhbiB3YXMgYW4gaW1wb3J0YW50IGZlYXR1cmUuIElmIHRoZSBwaGkgZXN0aW1hdGUgaXMgdmVyeSBoaWdoLCB0aGlzIG1lYW5zIHRoZSBkYXRhIHdhcyBjb25jZW50cmF0ZWQgYXJvdW5kIHRoZSBtZWFuIChmaW5lcyBwcm9wb3J0aW9uIGRvZXNuJ3QgZmx1Y3R1YXRlIG11Y2ggYmV0d2VlbiBzaXRlcy90aW1lcykuIENvbnNpZGVyIHBoaSBvZiAwLjEgdG8gYmUgc3ByZWFkIG91dCBkYXRhLCAxIHRvIGJlIG1vZGVyYXRlLCBhbmQgMTAgdG8gYmUgY29uY2VudHJhdGVkIGFyb3VuZCB0aGUgbWVhbi4NCg0KLSBQc2V1ZG8gUi1zcXVhcmVkOiB0aGlzIGlzIGhvdyBtdWNoIG9mIHRoZSB2YXJpYXRpb24gaW4gZmluZXMgaW4gcG9vbHMgY2FuIGJlIGV4cGxhaW5lZCBieSB0aGUgc2l0ZSBhbmQgdGltZSB2YXJpYWJsZXMuIE9mdGVuIGxvdyBpbiBlY29sb2dpY2FsIGNvbnRleHRzLg0KDQpOZXh0IHVwIGFyZSB0aGUgcHJvbWlzZWQgcGxvdHMgdGhhdCBzaG93IHRoZSBkaXN0cmlidXRpb24gb2YgZmluZXMgYW5kIGFxdWF0aWNzIGFjcm9zcyB0aGUgcmVhY2gsIHdoaWNoIHNob3VsZCBmYWNpbGl0YXRlIGludGVycHJldGF0aW9uLg0KDQojIENvbXBvc2l0ZSBGaWd1cmUNCg0KVGhpcyBmaWd1cmUganV4dGFwb3NlcyB0aGUgcGxvdHMgc2hvd2luZyB0aGUgcmVzaWR1YWwgc3VyZmFjZXMgd2l0aCB0aGUgcHJlc2VuY2UvYWJzZW5jZSByZWNvcmQgb2YgZmluZSBzZWRpbWVudHMsIGFuZCB3aXRoIHRoZSB3ZXR0ZWQgd2lkdGggcHJvcG9ydGlvbiBvZiB0aGUgdGhyZWUgY2F0ZWdvcmllcyBvZiBhcXVhdGljIHZlZ2V0YXRpb24uIFdoZXJlIGZhY3RvcnMgbGlrZSBleGNlc3Mgc2VkaW1lbnRhdGlvbiwgZXV0cm9waGljYXRpb24sIGludmFzaXZlIGFxdWF0aWNzLCBleGNlc3NpdmVseSBmbHVjdHVhdGluZyBkaXNzb2x2ZWQgb3h5Z2VuLCBhbmQvb3IgbGFjayBvZiBwb29sIGhhYml0YXQgaXMgYSBjb25jZXJuLCB0aGlzIGZpZ3VyZSBzaG91bGQgYmUgdXNlZnVsIHRvIHZpc3VhbGx5IGNvbXBhcmUgcmVhY2hlcyBvciB0cmFjayBjaGFuZ2VzIG92ZXIgdGltZS4gDQoNClJlbWVtYmVyIHRoYXQgaW4gYSBCQUNJIHN0dWR5IG91ciBwcmltYXJ5IGludGVyZXN0IGlzIHdoZXRoZXIgb3VyIHJlc3RvcmF0aW9uIHNpdGUgY2hhbmdlZCBpbiBhIGRpZmZlcmVudCB3YXkgdGhhbiB0aGUgY29udHJvbC9yZWZlcmVuY2Ugc2l0ZXMgY2hhbmdlZCBhY3Jvc3MgdGltZSAtIHRoaXMgaXMgbm90IGFsd2F5cyBlYXN5IHRvIHNlZSBpbiBmaWd1cmVzLCBzbyBjb25zaWRlciB0aGUgZmlndXJlIGFsb25nc2lkZSB0aGUgaW5mZXJlbnRpYWwgdGVzdCByZXN1bHRzIGZyb20gYWJvdmUuIEJlYXIgaW4gbWluZCB0aGF0IHRoZSBmaWd1cmUgcHJlc2VudHMgZGF0YSBieSB5ZWFyIHdoZXJlYXMgb3VyIGluZmVyZW50aWFsIHRlc3RzIGNvbnNpZGVyIGJlZm9yZSB2cyBhZnRlciB0aW1lIGNhdGVnb3JpZXMuDQoNCklmIHlvdSBoYXZlIHNldmVyYWwgc2l0ZXMveWVhcnMsIHlvdSBjYW4gbW9kaWZ5IHRoZSBjb2RlIGJlbG93IHRvIGNob29zZSB3aGljaCBmaWd1cmVzIGFyZSBwbG90dGVkIGluIFJTdHVkaW8uIElmIGxlZnQgYXQgTlVMTCBzaXRlIGFuZCBOVUxMIHllYXIsIHRoZSBjb2RlIHdpbGwgZGlzcGxheSBhbGwgc2l0ZS15ZWFycyBpbiBvbmUgY29tcG9zaXRlIGZpZ3VyZS4gWW91IGNhbiBhbHRlciB0aGlzIGNvZGUgdG8gZGlzcGxheSBvbmUgeWVhciBmb3Igb25lIHNpdGUsIGFsbCB5ZWFycyBmb3Igb25lIHNpdGUsIG9yIGFsbCBzaXRlcyBmb3Igb25lIHllYXIuIA0KDQpSZWdhcmRsZXNzIG9mIHdoYXQgeW91IHZpZXcgaW4gUlN0dWRpbywgdGhlIGNvZGUgd2lsbCBleHBvcnQgYWxsIGluZGl2aWR1YWwgc2l0ZS15ZWFyIHBsb3RzIGFuZCB0aGUgZnVsbCBjb21wb3NpdGUgZmlndXJlIGFzIGh0bWwgZmlsZXMgdG8geW91ciBvdXRwdXQgZm9sZGVyLg0KDQpgYGB7ciBzcGVjaWZ5IHNpdGUgYW5kIHllYXJ9DQojIFVzZXItZGVmaW5lZCBzaXRlIGFuZCB5ZWFyIGZvciBpbmRpdmlkdWFsIHBsb3QgZGlzcGxheQ0Kc2VsZWN0ZWRfc2l0ZSA8LSBOVUxMICMgUmVwbGFjZSB3aXRoIHRoZSBkZXNpcmVkICJzaXRlIG5hbWUiIChpbmNsdWRlIHRoZSBxdW90YXRpb24gbWFya3MpIG9yIHVzZSBOVUxMIGZvciBhbGwgc2l0ZXMNCnNlbGVjdGVkX3llYXIgPC0gTlVMTCAjIFJlcGxhY2Ugd2l0aCB0aGUgZGVzaXJlZCB5ZWFyIChubyBicmFja2V0cykgb3IgdXNlIE5VTEwgZm9yIGFsbCB5ZWFycw0KYGBgDQoNCmBgYHtyIGZ1bmN0aW9uIGNyZWF0aW5nIHNlcGFyYXRlIG11bHRpcGxvdHMgZm9yIGVhY2ggc2l0ZS15ZWFyLCBlY2hvPUZBTFNFfQ0KIyBDb252ZXJ0ICd5ZWFyJyBpbiBkYXRhZnJhbWVzIHRvIG51bWVyaWMgKGlmIGZhY3RvciwgbWF5IGNhdXNlIGZpbHRlcmluZyBpc3N1ZXMpDQpyZXNpZHVhbHMuZGYgPC0gcmVzaWR1YWxzLmRmICU+JQ0KICBtdXRhdGUoeWVhciA9IGFzLm51bWVyaWMoYXMuY2hhcmFjdGVyKHllYXIpKSkNCg0KIyBDYWxjdWxhdGUgdGhlIGdsb2JhbCB5LWF4aXMgbGltaXRzIGZvciBEZXB0aCAobSkgYWNyb3NzIHRoZSBlbnRpcmUgZGF0YXNldCwgZm9yIHZpc3VhbCBjb21wYXJpc29uIG9uIHNhbWUgc2NhbGVkIHktYXhlcw0KZ2xvYmFsX2RlcHRoX2xpbWl0cyA8LSByZXNpZHVhbHMuZGYgJT4lDQogIGZpbHRlcihkaXN0YW5jZSA+PSAwKSAlPiUNCiAgc3VtbWFyaXNlKA0KICAgIGdsb2JhbF9taW5fZGVwdGggPSAwLCAgIyBrZWVwIG1pbiBkZXB0aCBhdCAwDQogICAgZ2xvYmFsX21heF9kZXB0aCA9IG1heChUaGFsd2VnX0RlcHRoX20sIG5hLnJtID0gVFJVRSkgICAjIENhbGN1bGF0ZSBtYXhpbXVtIGRlcHRoIGZyb20gdGhlIGRhdGENCiAgKQ0KDQojIEZ1bmN0aW9uIHRvIGdlbmVyYXRlIHRoZSBwbG90cyBmb3IgYSBnaXZlbiBzaXRlLXllYXIgY29tYmluYXRpb24NCmdlbmVyYXRlX3NpdGVfeWVhcl9wbG90cyA8LSBmdW5jdGlvbihyZXNpZHVhbHMuZGYsIHNpdGUsIHNlbGVjdGVkX3llYXIsIGdsb2JhbF9taW5fZGVwdGgsIGdsb2JhbF9tYXhfZGVwdGgpIHsNCiAgDQogICMgRmlsdGVyIGRhdGEgZm9yIHRoZSBzcGVjaWZpYyBzaXRlIGFuZCB5ZWFyIChpc29sYXRlZCBoZXJlKQ0KICBzaXRlX3llYXJfZGF0YSA8LSByZXNpZHVhbHMuZGYgJT4lDQogICAgZmlsdGVyKA0KICAgICAgICB0cmltd3MoU2l0ZSkgPT0gdHJpbXdzKHNpdGUpICYgDQogICAgICAgIHllYXIgPT0gYXMubnVtZXJpYyhzZWxlY3RlZF95ZWFyKSAmIA0KICAgICAgICBkaXN0YW5jZSA+PSAwDQogICAgKSAlPiUNCiAgICBtdXRhdGUoRmluZXNfcHJlc2VuY2UgPSBpZmVsc2UodG9sb3dlcihGaW5lcykgJWluJSBjKCJ5IiwgInllcyIpLCAxLCAwKSkNCiAgDQogICMgRGVmaW5lIGNvbnNpc3RlbnQgeC1heGlzIGxpbWl0cyAoc2hvdWxkIGJlIGJhc2VkIG9uIHRoZSBmaWx0ZXJlZCBkYXRhKQ0KICB4X2xpbWl0cyA8LSByYW5nZShzaXRlX3llYXJfZGF0YSRkaXN0YW5jZSwgbmEucm0gPSBUUlVFKQ0KICANCiAgIyBQbG90IDE6IFRoYWx3ZWcgRGVwdGggYW5kIFJlc2lkdWFsIFN1cmZhY2Ugd2l0aCBzdGFuZGFyZGl6ZWQgeS1heGlzDQogIHBsb3RfcmVzaWR1YWxzIDwtIHBsb3RfbHkoc2l0ZV95ZWFyX2RhdGEsIHggPSB+ZGlzdGFuY2UsIHkgPSB+VGhhbHdlZ19EZXB0aF9tLCB0eXBlID0gJ3NjYXR0ZXInLCBtb2RlID0gJ2xpbmVzJywNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBuYW1lID0gJ1RoYWx3ZWcgRGVwdGgnLCBsaW5lID0gbGlzdChjb2xvciA9ICdibGFjaycsIHdpZHRoID0gMikpICU+JQ0KICAgIGFkZF90cmFjZSh5ID0gfnJlc2lkdWFsX3N1cmZhY2UsIG1vZGUgPSAnbGluZXMnLCBuYW1lID0gJ1Jlc2lkdWFsIFN1cmZhY2UnLCBsaW5lID0gbGlzdChjb2xvciA9ICdibHVlJywgd2lkdGggPSAyKSkgJT4lDQogICAgbGF5b3V0KA0KICAgICAgeWF4aXMgPSBsaXN0KA0KICAgICAgICB0aXRsZSA9ICJEZXB0aCAobSkiLCANCiAgICAgICAgcmFuZ2UgPSBjKGdsb2JhbF9tYXhfZGVwdGgsIGdsb2JhbF9taW5fZGVwdGgpLCAgIyBVc2UgZ2xvYmFsIGRlcHRoIGxpbWl0cw0KICAgICAgICBhdXRvcmFuZ2UgPSBGQUxTRQ0KICAgICAgKSwNCiAgICAgIHhheGlzID0gbGlzdChyYW5nZSA9IHhfbGltaXRzKSwNCiAgICAgIHNob3dsZWdlbmQgPSBUUlVFDQogICAgKQ0KICANCiAgIyBQbG90IDI6IFN1Ym1lcmdlZCBWZWdldGF0aW9uIFByb3BvcnRpb24NCiAgcGxvdF9zdWJ2ZWcgPC0gcGxvdF9seShzaXRlX3llYXJfZGF0YSwgeCA9IH5kaXN0YW5jZSwgeSA9IH5zdWJ2ZWcsIHR5cGUgPSAnc2NhdHRlcicsIG1vZGUgPSAnbGluZXMnLA0KICAgICAgICAgICAgICAgICAgICAgICAgIGxpbmUgPSBsaXN0KGNvbG9yID0gJ2RhcmtncmVlbicsIHdpZHRoID0gMiksIGZpbGwgPSAndG96ZXJveScsIGZpbGxjb2xvciA9ICdkYXJrZ3JlZW4nKSAlPiUNCiAgICBsYXlvdXQoDQogICAgICB5YXhpcyA9IGxpc3QodGl0bGUgPSAiU3VidmVnIFByb3BvcnRpb25hbCBDb3ZlciIsIHJhbmdlID0gYygwLCAxKSksDQogICAgICB4YXhpcyA9IGxpc3QocmFuZ2UgPSB4X2xpbWl0cyksDQogICAgICBzaG93bGVnZW5kID0gRkFMU0UNCiAgICApDQogIA0KICAjIFBsb3QgMzogRmxvYXRpbmcgVmVnZXRhdGlvbiBQcm9wb3J0aW9uDQogIHBsb3RfZmxvYXR2ZWcgPC0gcGxvdF9seShzaXRlX3llYXJfZGF0YSwgeCA9IH5kaXN0YW5jZSwgeSA9IH5mbG9hdHZlZywgdHlwZSA9ICdzY2F0dGVyJywgbW9kZSA9ICdsaW5lcycsDQogICAgICAgICAgICAgICAgICAgICAgICAgICBsaW5lID0gbGlzdChjb2xvciA9ICdmb3Jlc3RncmVlbicsIHdpZHRoID0gMiksIGZpbGwgPSAndG96ZXJveScsIGZpbGxjb2xvciA9ICdmb3Jlc3RncmVlbicpICU+JQ0KICAgIGxheW91dCgNCiAgICAgIHlheGlzID0gbGlzdCh0aXRsZSA9ICJGbG9hdHZlZyBQcm9wb3J0aW9uYWwgQ292ZXIiLCByYW5nZSA9IGMoMCwgMSkpLA0KICAgICAgeGF4aXMgPSBsaXN0KHJhbmdlID0geF9saW1pdHMpLA0KICAgICAgc2hvd2xlZ2VuZCA9IEZBTFNFDQogICAgKQ0KICANCiAgIyBQbG90IDQ6IEVtZXJnZW50IFZlZ2V0YXRpb24gUHJvcG9ydGlvbg0KICBwbG90X2VtZXJndmVnIDwtIHBsb3RfbHkoc2l0ZV95ZWFyX2RhdGEsIHggPSB+ZGlzdGFuY2UsIHkgPSB+ZW1lcmd2ZWcsIHR5cGUgPSAnc2NhdHRlcicsIG1vZGUgPSAnbGluZXMnLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgbGluZSA9IGxpc3QoY29sb3IgPSAnbGlnaHRncmVlbicsIHdpZHRoID0gMiksIGZpbGwgPSAndG96ZXJveScsIGZpbGxjb2xvciA9ICdsaWdodGdyZWVuJykgJT4lDQogICAgbGF5b3V0KA0KICAgICAgeWF4aXMgPSBsaXN0KHRpdGxlID0gIkVtZXJndmVnIFByb3BvcnRpb25hbCBDb3ZlciIsIHJhbmdlID0gYygwLCAxKSksDQogICAgICB4YXhpcyA9IGxpc3QocmFuZ2UgPSB4X2xpbWl0cyksDQogICAgICBzaG93bGVnZW5kID0gRkFMU0UNCiAgICApDQogIA0KICAjIFBsb3QgNTogRmluZXMgUHJlc2VuY2UvQWJzZW5jZQ0KICBwbG90X2ZpbmVzIDwtIHBsb3RfbHkoc2l0ZV95ZWFyX2RhdGEsIHggPSB+ZGlzdGFuY2UsIHkgPSB+RmluZXNfcHJlc2VuY2UsIHR5cGUgPSAnc2NhdHRlcicsIG1vZGUgPSAnbGluZXMnLA0KICAgICAgICAgICAgICAgICAgICAgICAgbGluZSA9IGxpc3QoY29sb3IgPSAnYnVybHl3b29kMycsIHdpZHRoID0gMiksIGZpbGwgPSAndG96ZXJveScsIGZpbGxjb2xvciA9ICdidXJseXdvb2QzJykgJT4lDQogICAgbGF5b3V0KA0KICAgICAgeWF4aXMgPSBsaXN0KHRpdGxlID0gIkZpbmUgU2VkaW1lbnRzIiwgdGlja3ZhbHMgPSBjKDAsIDEpLCB0aWNrdGV4dCA9IGMoJ2FicycsICdwcmVzJyksIHJhbmdlID0gYygwLCAxKSksDQogICAgICB4YXhpcyA9IGxpc3QodGl0bGUgPSAiZGlzdGFuY2UgKG0pIiwgcmFuZ2UgPSB4X2xpbWl0cyksDQogICAgICBzaG93bGVnZW5kID0gRkFMU0UNCiAgICApDQogIA0KICAjIENvbWJpbmUgdGhlIHBsb3RzIGludG8gYSB2ZXJ0aWNhbCBncmlkDQogIHN1YnBsb3QoDQogICAgcGxvdF9yZXNpZHVhbHMgJT4lIGxheW91dCgNCiAgICAgIHlheGlzID0gbGlzdCgNCiAgICAgICAgdGl0bGUgPSAiRGVwdGggKG0pIiwgDQogICAgICAgIHJhbmdlID0gYyhnbG9iYWxfbWF4X2RlcHRoLCBnbG9iYWxfbWluX2RlcHRoKSwgICMgRW5zdXJlIGRlcHRoIGF4aXMgaXMgc2hhcmVkDQogICAgICAgIGF1dG9yYW5nZSA9IEZBTFNFLCANCiAgICAgICAgYXV0b21hcmdpbiA9IFRSVUUNCiAgICAgICkNCiAgICApLA0KICAgIHBsb3RfZW1lcmd2ZWcgJT4lIGxheW91dCh5YXhpcyA9IGxpc3QodGl0bGUgPSAiRW1lcmdlbnQgVmVnXG5Qcm9wb3J0aW9uYWwgQ292ZXIiLCByYW5nZSA9IGMoMCwgMSksIGF1dG9tYXJnaW4gPSBUUlVFKSksDQogICAgcGxvdF9mbG9hdHZlZyAlPiUgbGF5b3V0KHlheGlzID0gbGlzdCh0aXRsZSA9ICJGbG9hdGluZyBWZWdcblByb3BvcnRpb25hbCBDb3ZlciIsIHJhbmdlID0gYygwLCAxKSwgYXV0b21hcmdpbiA9IFRSVUUpKSwNCiAgICBwbG90X3N1YnZlZyAlPiUgbGF5b3V0KHlheGlzID0gbGlzdCh0aXRsZSA9ICJTdWJtZXJnZWQgVmVnXG5Qcm9wb3J0aW9uYWwgQ292ZXIiLCByYW5nZSA9IGMoMCwgMSksIGF1dG9tYXJnaW4gPSBUUlVFKSksDQogICAgcGxvdF9maW5lcyAlPiUgbGF5b3V0KHlheGlzID0gbGlzdCh0aXRsZSA9ICJGaW5lXG5TZWRpbWVudCIsIHRpY2t2YWxzID0gYygwLCAxKSwgdGlja3RleHQgPSBjKCJBYnMiLCAiUHJlcyIpLCBhdXRvbWFyZ2luID0gVFJVRSkpLA0KICAgIG5yb3dzID0gNSwNCiAgICBoZWlnaHRzID0gYygwLjUsIDAuMTI1LCAwLjEyNSwgMC4xMjUsIDAuMTI1KSwNCiAgICBzaGFyZVggPSBUUlVFLA0KICAgIHNoYXJlWSA9IFRSVUUgICMgU2hhcmUgeS1heGlzIGFjcm9zcyBhbGwgcGxvdHMNCiAgKSAlPiUNCiAgbGF5b3V0KA0KICAgIHRpdGxlID0gcGFzdGUoc2l0ZSwgc2VsZWN0ZWRfeWVhciwgIlRoYWx3ZWcgTG9uZ2l0dWRpbmFsIFByb2ZpbGUiKSwNCiAgICBtYXJnaW4gPSBsaXN0KHQgPSA1MCwgbCA9IDUwLCBiID0gNTApLCAgIyBJbmNyZWFzZSBsZWZ0IG1hcmdpbg0KICAgIHhheGlzID0gbGlzdCh0aXRsZSA9ICJkaXN0YW5jZSAobSkiKSwgICMgU2hhcmVkIHgtYXhpcyBsYWJlbA0KICAgIHlheGlzID0gbGlzdCh0aXRsZSA9ICJEZXB0aCAobSkiLCBhdXRvbWFyZ2luID0gVFJVRSwgdGl0bGVmb250ID0gbGlzdChzaXplPTEwKSksDQogICAgeWF4aXMyID0gbGlzdCh0aXRsZSA9ICJFbWVyZ1xuQ292ZXIiLCBhdXRvbWFyZ2luID0gVFJVRSwgdGl0bGVmb250ID0gbGlzdChzaXplPTEwKSksDQogICAgeWF4aXMzID0gbGlzdCh0aXRsZSA9ICJGbG9hdFxuQ292ZXIiLCBhdXRvbWFyZ2luID0gVFJVRSwgdGl0bGVmb250ID0gbGlzdChzaXplPTEwKSksDQogICAgeWF4aXM0ID0gbGlzdCh0aXRsZSA9ICJTdWJcbkNvdmVyIiwgYXV0b21hcmdpbiA9IFRSVUUsIHRpdGxlZm9udCA9IGxpc3Qoc2l6ZT0xMCkpLA0KICAgIHlheGlzNSA9IGxpc3QodGl0bGUgPSAiRmluZXMiLCBhdXRvbWFyZ2luID0gVFJVRSwgdGl0bGVmb250ID0gbGlzdChzaXplPTEwKSkNCiAgKQ0KfQ0KDQojIEdlbmVyYXRlIHVuaXF1ZSBzaXRlLXllYXIgY29tYmluYXRpb25zDQpzaXRlX3llYXJfY29tYmluYXRpb25zIDwtIHJlc2lkdWFscy5kZiAlPiUNCiAgZGlzdGluY3QoU2l0ZSwgeWVhcikgJT4lDQogIGFycmFuZ2UoU2l0ZSwgeWVhcikNCg0KIyBEaXNwbGF5IGVpdGhlciB0aGUgc2VsZWN0ZWQgc2l0ZS15ZWFyIHBsb3Qgb3IgYWxsIGNvbXBvc2l0ZSBwbG90cw0KaWYgKCFpcy5udWxsKHNlbGVjdGVkX3NpdGUpICYgIWlzLm51bGwoc2VsZWN0ZWRfeWVhcikpIHsNCiAgIyBDYXNlIDE6IFNwZWNpZmljIHNpdGUteWVhciBwbG90DQogIHNlbGVjdGVkX3Bsb3QgPC0gZ2VuZXJhdGVfc2l0ZV95ZWFyX3Bsb3RzKA0KICAgIHJlc2lkdWFscy5kZiwgc2VsZWN0ZWRfc2l0ZSwgc2VsZWN0ZWRfeWVhciwNCiAgICBnbG9iYWxfZGVwdGhfbGltaXRzJGdsb2JhbF9taW5fZGVwdGgsIGdsb2JhbF9kZXB0aF9saW1pdHMkZ2xvYmFsX21heF9kZXB0aA0KICApDQogIHNlbGVjdGVkX3Bsb3QgICMgRGlzcGxheSB0aGUgcGxvdCBpbiBSU3R1ZGlvDQoNCn0gZWxzZSBpZiAoIWlzLm51bGwoc2VsZWN0ZWRfc2l0ZSkgJiBpcy5udWxsKHNlbGVjdGVkX3llYXIpKSB7DQogICMgQ2FzZSAyOiBBbGwgeWVhcnMgZm9yIGEgc3BlY2lmaWMgc2l0ZQ0KICBzaXRlX3Bsb3RzIDwtIHNpdGVfeWVhcl9jb21iaW5hdGlvbnMgJT4lDQogICAgZmlsdGVyKFNpdGUgPT0gc2VsZWN0ZWRfc2l0ZSkgJT4lDQogICAgcG1hcF9kZnIoZnVuY3Rpb24oU2l0ZSwgeWVhcikgew0KICAgICAgcGxvdCA8LSBnZW5lcmF0ZV9zaXRlX3llYXJfcGxvdHMoDQogICAgICAgIHJlc2lkdWFscy5kZiwgU2l0ZSwgeWVhciwNCiAgICAgICAgZ2xvYmFsX2RlcHRoX2xpbWl0cyRnbG9iYWxfbWluX2RlcHRoLCBnbG9iYWxfZGVwdGhfbGltaXRzJGdsb2JhbF9tYXhfZGVwdGgNCiAgICAgICkNCiAgICAgIHRpYmJsZShwbG90ID0gbGlzdChwbG90KSwgeWVhciA9IHllYXIpDQogICAgfSkNCiAgDQogICMgQXJyYW5nZSBwbG90cyBmb3IgdGhlIHNpdGUgYWNyb3NzIGFsbCB5ZWFycw0KICBjb21iaW5lZF9zaXRlX3Bsb3QgPC0gc3VicGxvdCgNCiAgICBsYXBwbHkoc2l0ZV9wbG90cyRwbG90LCBpZGVudGl0eSksDQogICAgbnJvd3MgPSBucm93KHNpdGVfcGxvdHMpLCAgIyBPbmUgcm93IHBlciB5ZWFyDQogICAgdGl0bGVYID0gRkFMU0UsDQogICAgdGl0bGVZID0gVFJVRQ0KICApICU+JQ0KICAgIGxheW91dCh0aXRsZSA9IHBhc3RlKCJQbG90cyBmb3IgU2l0ZToiLCBzZWxlY3RlZF9zaXRlKSkNCiAgY29tYmluZWRfc2l0ZV9wbG90ICAjIERpc3BsYXkgdGhlIHBsb3QNCg0KfSBlbHNlIGlmIChpcy5udWxsKHNlbGVjdGVkX3NpdGUpICYgIWlzLm51bGwoc2VsZWN0ZWRfeWVhcikpIHsNCiAgIyBDYXNlIDM6IEFsbCBzaXRlcyBmb3IgYSBzcGVjaWZpYyB5ZWFyDQogIHllYXJfcGxvdHMgPC0gc2l0ZV95ZWFyX2NvbWJpbmF0aW9ucyAlPiUNCiAgICBmaWx0ZXIoeWVhciA9PSBzZWxlY3RlZF95ZWFyKSAlPiUNCiAgICBwbWFwX2RmcihmdW5jdGlvbihTaXRlLCB5ZWFyKSB7DQogICAgICBwbG90IDwtIGdlbmVyYXRlX3NpdGVfeWVhcl9wbG90cygNCiAgICAgICAgcmVzaWR1YWxzLmRmLCBTaXRlLCB5ZWFyLA0KICAgICAgICBnbG9iYWxfZGVwdGhfbGltaXRzJGdsb2JhbF9taW5fZGVwdGgsIGdsb2JhbF9kZXB0aF9saW1pdHMkZ2xvYmFsX21heF9kZXB0aA0KICAgICAgKQ0KICAgICAgdGliYmxlKHBsb3QgPSBsaXN0KHBsb3QpLCBzaXRlID0gU2l0ZSkNCiAgICB9KQ0KICANCiAgIyBBcnJhbmdlIHBsb3RzIGZvciB0aGUgeWVhciBhY3Jvc3MgYWxsIHNpdGVzDQogIGNvbWJpbmVkX3llYXJfcGxvdCA8LSBzdWJwbG90KA0KICAgIGxhcHBseSh5ZWFyX3Bsb3RzJHBsb3QsIGlkZW50aXR5KSwNCiAgICBucm93cyA9IG5yb3coeWVhcl9wbG90cyksICAjIE9uZSByb3cgcGVyIHNpdGUNCiAgICB0aXRsZVggPSBGQUxTRSwNCiAgICB0aXRsZVkgPSBUUlVFDQogICkgJT4lDQogICAgbGF5b3V0KHRpdGxlID0gcGFzdGUoIlBsb3RzIGZvciBZZWFyOiIsIHNlbGVjdGVkX3llYXIpKQ0KICBjb21iaW5lZF95ZWFyX3Bsb3QgICMgRGlzcGxheSB0aGUgcGxvdA0KDQp9IGVsc2Ugew0KICAjIENhc2UgNDogQWxsIHNpdGUteWVhciBjb21iaW5hdGlvbnMgDQogIGNvbXBvc2l0ZV9wbG90cyA8LSBzaXRlX3llYXJfY29tYmluYXRpb25zICU+JQ0KICAgIHBtYXBfZGZyKGZ1bmN0aW9uKFNpdGUsIHllYXIpIHsNCiAgICAgIHBsb3QgPC0gZ2VuZXJhdGVfc2l0ZV95ZWFyX3Bsb3RzKA0KICAgICAgICByZXNpZHVhbHMuZGYsIFNpdGUsIHllYXIsDQogICAgICAgIGdsb2JhbF9kZXB0aF9saW1pdHMkZ2xvYmFsX21pbl9kZXB0aCwgZ2xvYmFsX2RlcHRoX2xpbWl0cyRnbG9iYWxfbWF4X2RlcHRoDQogICAgICApDQogICAgICB0aWJibGUocGxvdCA9IGxpc3QocGxvdCksIHNpdGUgPSBTaXRlLCB5ZWFyID0geWVhcikNCiAgICB9KQ0KICANCiAgIyBHcm91cCBwbG90cyBieSBzaXRlDQogIHNpdGVfcGxvdHMgPC0gY29tcG9zaXRlX3Bsb3RzICU+JQ0KICAgIGdyb3VwX2J5KHNpdGUpICU+JQ0KICAgIGdyb3VwX21hcChmdW5jdGlvbihzaXRlX3Bsb3RzLCBzaXRlKSB7DQogICAgICBzdWJwbG90KA0KICAgICAgICBsYXBwbHkoc2l0ZV9wbG90cyRwbG90LCBpZGVudGl0eSksDQogICAgICAgIG5yb3dzID0gMSwgICMgT25lIHJvdyBmb3IgZWFjaCBzaXRlDQogICAgICAgIHRpdGxlWCA9IEZBTFNFLA0KICAgICAgICB0aXRsZVkgPSBUUlVFDQogICAgICApICU+JQ0KICAgICAgICBsYXlvdXQodGl0bGUgPSBsaXN0KHRleHQgPSBzaXRlLCBmb250ID0gbGlzdChzaXplID0gMTYpKSkNCiAgICB9KQ0KICANCiAgIyBDb21iaW5lIGFsbCBzaXRlIHJvd3MNCiAgY29tYmluZWRfcGxvdCA8LSBzdWJwbG90KA0KICAgIHNpdGVfcGxvdHMsDQogICAgbnJvd3MgPSBsZW5ndGgoc2l0ZV9wbG90cyksICAjIE9uZSByb3cgcGVyIHNpdGUNCiAgICB0aXRsZVggPSBUUlVFLA0KICAgIHRpdGxlWSA9IFRSVUUNCiAgKSAlPiUNCiAgICBsYXlvdXQodGl0bGUgPSAiTG9uZyBQcm9maWxlIENvbXBvc2l0ZSBQbG90cyBieSBTaXRlLVllYXIiKQ0KICANCiAgY29tYmluZWRfcGxvdCAgIyBEaXNwbGF5IHRoZSBjb21iaW5lZCBwbG90DQp9DQoNCiMgRXhwb3J0IEFMTCBpbmRpdmlkdWFsIHNpdGUteWVhciBwbG90cyBhcyBIVE1MDQppbnZpc2libGUoc2l0ZV95ZWFyX2NvbWJpbmF0aW9ucyAlPiUNCiAgcG1hcChmdW5jdGlvbihTaXRlLCB5ZWFyKSB7DQogICAgcGxvdCA8LSBnZW5lcmF0ZV9zaXRlX3llYXJfcGxvdHMoDQogICAgICByZXNpZHVhbHMuZGYsIFNpdGUsIHllYXIsDQogICAgICBnbG9iYWxfZGVwdGhfbGltaXRzJGdsb2JhbF9taW5fZGVwdGgsIGdsb2JhbF9kZXB0aF9saW1pdHMkZ2xvYmFsX21heF9kZXB0aA0KICAgICkNCiAgICANCiAgICAjIFNhdmUgZWFjaCBpbmRpdmlkdWFsIHBsb3QgYXMgYW4gSFRNTCBmaWxlDQogICAgZXhwb3J0X3Bsb3QocGxvdCwgcGFzdGUwKCJMb25nIFByb2ZpbGUgQ29tcG9zaXRlICIsIFNpdGUsICJfIiwgeWVhciwgIi5odG1sIikpDQogIH0pDQopDQogIA0KI2V4cG9ydCBjb21iaW5lZCBwbG90IA0KaWYgKGV4aXN0cygiY29tYmluZWRfcGxvdCIpKSB7DQogIGV4cG9ydF9wbG90KGNvbWJpbmVkX3Bsb3QsICJMb25nIFByb2ZpbGUgQ29tcG9zaXRlIFBsb3QgQWxsIFNpdGUgWWVhcnMuaHRtbCIpDQp9DQpgYGANCg0KTm93IHRoYXQgeW91IGhhdmUgdmlzdWFsaXNhdGlvbnMgb2YgdGhlIHJlc2lkdWFsIHBvb2wgZGF0YSwgYW5kIHN0YXRpc3RpY2FsIHRlc3RzIHRvIGV4YW1pbmUgdGhlIHN0YXRpc3RpY2FsIHNpZ25pZmljYW5jZSBvZiBkaWZmZXJlbmNlcyBpbiByZWFjaCBwb29sIGNoYXJhY3RlcmlzdGljcyBhbW9uZyByZWFjaGVzIGFuZCB5ZWFycywgaXQgaXMgdGltZSB0byBjb25zaWRlciB0aGUgYmlvbG9naWNhbC9tb3JwaG9sb2dpY2FsIHNpZ25pZmljYW5jZSBhbmQgdGhlIGltcGxpY2F0aW9ucyBmb3IgeW91ciBwcm9qZWN0Lg0KDQojIE5leHQgU3RlcHMNCg0KV2UgY2FuIG5vdyBtb3ZlIG9uIHRvIGxvb2tpbmcgYXQgYSBmZXcgbW9yZSBjb21wb25lbnRzIG9mIGhhYml0YXQgdGhhdCBtYXkgYmUgdXNlZnVsIHRvIG1vbml0b3IgZm9yIHlvdXIgcHJvamVjdC4gV2Ugd2lsbCBleHBvcnQgdGhlIHJlc2lkdWFsIHBvb2wgZGF0YSB3ZSBnZW5lcmF0ZWQgaW4gdGhpcyBjb2RlIGZvciB1c2UgbGF0ZXIgb24gKHdoZW4gY29uc2lkZXJpbmcgaGFiaXRhdCB1bml0IGNsYXNzaWZpY2F0aW9ucykuIFRoaXMgd2lsbCBiZSBleHBvcnRlZCB0byB5b3VyIG91dHB1dCBmb2xkZXIgKHdoaWNoIGJ5IG5vdywgbWlnaHQgYmUgYSBiaXQgYnVzeS4gSWYgbW92aW5nIGZpbGVzIGFyb3VuZCwgcmVtZW1iZXIgdGhhdCB0aGUgaHRtbCBmaWxlcyBuZWVkIHRvIGJlIGluIHRoZSBzYW1lIGZvbGRlciBhcyB0aGVpciBzaW1pbGFybHktbmFtZWQgZGVwZW5kZW5jeSBmb2xkZXJzKS4NCg0KYGBge3IgcmVzaWR1YWxzLmRmIGV4cG9ydCwgZWNobz1GQUxTRX0NCmV4cG9ydF90YWJsZShhcy5kYXRhLmZyYW1lKHJlc2lkdWFscy5kZiksIlJlc2lkdWFsc19kYXRhZnJhbWUuY3N2IikNCmBgYA0KDQojIFJlZmVyZW5jZXMgDQoNCkNsYXJrLCBDLiwgUm9uaSwgUC4gYW5kIEJ1cmdlc3MsIFMuLCAyMDE5LiBSZXNwb25zZSBvZiBqdXZlbmlsZSBzYWxtb25pZHMgdG8gbGFyZ2Ugd29vZCBwbGFjZW1lbnQgaW4gQ29sdW1iaWEgUml2ZXIgdHJpYnV0YXJpZXMuIEh5ZHJvYmlvbG9naWEsIDg0MigxKSwgcHAuMTczLTE5MC4NCg0KR2Vpc3NpbmdlciwgRS5BLiwgS2hvbywgQy5MLiwgUmljaG1vbmQsIEkuQy4sIEZhdWxrbmVyLCBTLkouIGFuZCBTY2huZWlkZXIsIEQuQy4sIDIwMjIuIEEgY2FzZSBmb3IgYmV0YSByZWdyZXNzaW9uIGluIHRoZSBuYXR1cmFsIHNjaWVuY2VzLiBFY29zcGhlcmUsIDEzKDIpLCBwLmUzOTQwLg0KDQpLYXVmbWFubiwgUC5SLiwgTGV2aW5lLCBQLiwgUGVjaywgRC5WLiwgUm9iaXNvbiwgRS5HLiBhbmQgU2VlbGlnZXIsIEMuLCAxOTk5LiBRdWFudGlmeWluZyBwaHlzaWNhbCBoYWJpdGF0IGluIHdhZGVhYmxlIHN0cmVhbXMgKHAuIDE0OSkuIFVTRVBBIFtOYXRpb25hbCBIZWFsdGggYW5kIEVudmlyb25tZW50YWwgRWZmZWN0cyBSZXNlYXJjaCBMYWJvcmF0b3J5LCBXZXN0ZXJuIEVjb2xvZ3kgRGl2aXNpb25dLg0KDQpMaXNsZSwgVC5FLiwgMTk4Ni4gRWZmZWN0cyBvZiB3b29keSBkZWJyaXMgb24gYW5hZHJvbW91cyBzYWxtb25pZCBoYWJpdGF0LCBQcmluY2Ugb2YgV2FsZXMgSXNsYW5kLCBzb3V0aGVhc3QgQWxhc2thLiBOb3J0aCBBbWVyaWNhbiBKb3VybmFsIG9mIEZpc2hlcmllcyBNYW5hZ2VtZW50LCA2KDQpLCBwcC41MzgtNTUwLg0KDQpMaXNsZSwgVC5FLiwgMTk4Ny4gVXNpbmciIHJlc2lkdWFsIGRlcHRocyIgdG8gbW9uaXRvciBwb29sIGRlcHRocyBpbmRlcGVuZGVudGx5IG9mIGRpc2NoYXJnZS4gUmVzLiBOb3RlIFBTVy1STi0zOTQuIEJlcmtlbGV5LCBDQTogVVMgRGVwYXJ0bWVudCBvZiBBZ3JpY3VsdHVyZSwgRm9yZXN0IFNlcnZpY2UsIFBhY2lmaWMgU291dGh3ZXN0IEZvcmVzdCBhbmQgUmFuZ2UgRXhwZXJpbWVudCBTdGF0aW9uLiA0IHAsIDM5NC4NCg0KTW9zc29wLCBCLiBhbmQgQnJhZGZvcmQsIE0uSi4sIDIwMDYuIFVzaW5nIHRoYWx3ZWcgcHJvZmlsaW5nIHRvIGFzc2VzcyBhbmQgbW9uaXRvciBqdXZlbmlsZSBzYWxtb24gKE9uY29yaHluY2h1cyBzcHAuKSBoYWJpdGF0IGluIHNtYWxsIHN0cmVhbXMuIENhbmFkaWFuIEpvdXJuYWwgb2YgRmlzaGVyaWVzIGFuZCBBcXVhdGljIFNjaWVuY2VzLCA2Myg3KSwgcHAuMTUxNS0xNTI1Lg0KDQpSb2Jpc29uLCBFLkcuLCAxOTk4LiBSZWFjaCBzY2FsZSBzYW1wbGluZyBtZXRyaWNzIGFuZCBsb25naXR1ZGluYWwgcGF0dGVybiBhZGp1c3RtZW50IG9mIHNtYWxsIHN0cmVhbXMuIFBoRCBUaGVzaXMuIE9yZWdvbiBTdGF0ZSBVbml2ZXJzaXR5Lg0KDQpTdGFjaywgVy5SLiwgMTk4OC4gRmFjdG9ycyBpbmZsdWVuY2luZyBwb29sIG1vcnBob2xvZ3kgaW4gT3JlZ29uIGNvYXN0YWwgc3RyZWFtcy4gTVNjIFRoZXNpcy4gT3JlZ29uIFN0YXRlIFVuaXZlcnNpdHk=